1

I have a PHP script that receives POST with multiple data (+30), all of them required. Instead of checking one by one with isset() and strlen(), as suggested here, would be great if I could catch the notice error "Undefined index" somehow. Researching on Google I found few old posts about this subject, like this one, so maybe there is some new technique or workaround to archive this goal.

UPDATE:

Based on @bishop answer, here is my solution:

try {

    if ($_SERVER['REQUEST_METHOD'] == 'POST') {

        $flds = ['data1', 'data2', 'data3'];
        if (count(array_diff($flds, array_keys($_POST))) > 0) {
            throw new Exception('Missing fields detected!');
        }

        /* @bishop solution    
        $vals = array_filter($_POST, function($val) { return ($val != ''); });
        if (count(array_diff($_POST, $vals)) > 0) {
             throw new Exception('Empty fields detected!');
        }
        */

        // I prefered using the bellow approach instead of @bishop
        // solution, once I will need to sanitize values anyway

        foreach($_POST as $input => $value) {
            $_POST[$input] = trim($value);
            if (strlen($_POST[$input]) === 0) {
                throw new Exception('Empty fields detected!');
            }
            //$_POST[$input] = mysqli_real_escape_string($conn, $value);
        }
    }

} catch (Exception $e) {
    echo $e->getMessage();
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Guybrush
  • 1,575
  • 2
  • 27
  • 51
  • You shouldn't use try...catch for validation. You can loop trough your `$_POST` array and check them individually instead of writing a line or two for each item. – Phiter Apr 27 '18 at 19:18
  • @Phiter, can't belive I didn't think about this solution! I will try to implement it in my code. Thank you! – Guybrush Apr 27 '18 at 19:29

1 Answers1

2

If you want to check that every field is present, you can use array_diff and array_filter:

// check for missing keys in the post data
$expect = [ 'data1', 'data2', 'data3' ];
if ($missing = array_diff($expect, array_keys($_POST))) {
    var_dump($missing);
}

// check for missing values in the post data: modify to suit
$passed = array_filter($_POST, function($value) { return ! empty($value); });
if ($invalid = array_diff($_POST, $passed)) {
    var_dump($invalid);
}

However, to do it the way you described:

// temporarily catch all raised errors, warnings, and notices
$errors = [];
set_error_handler(function ($code, $message, $file, $line, $context) use (&$errors) {
    $errors[] = [ $code, $message ];
});

// do your "validation"
if ($foo) {
    echo "foo";
}

// restore the state of the world, and check for errors
restore_error_handler();
if (count($errors)) {
    echo 'Bad bad!';
}

Use at your own risk, though. Generally it's best to positively check for the accepted value, and use any generated errors/warnings/notices as context for why your logic isn't working as expected.

Capturing errors for inspection is part of many frameworks. Some external libraries provide it, as well, like Haldayne/fox. Disclaimer: I'm the author of Haldayne.

bishop
  • 37,830
  • 11
  • 104
  • 139
  • Please, what are the risks? Thank you! – Guybrush Apr 27 '18 at 19:26
  • It's brittle. For example, PHP might start emitting a new notice in one of the functions you're using and suddenly your code stops working. – bishop Apr 27 '18 at 19:30
  • Ok, I will research and try to use your first (new) solution. Thank you! – Guybrush Apr 27 '18 at 19:31
  • Bishop, about your first solution, what about some expected data is missing (not set)? I mean, for example, I expect data1, data2, data3, data4 and data5, each one with some content. What about data2 is not include in the POST? – Guybrush Apr 27 '18 at 19:41
  • Please, see the question update with my solution, based in your answer. Do you think using `trim()` and `in_array('', $_POST)` is a good approach to verify empty values? Thank you again! – Guybrush Apr 27 '18 at 20:54
  • Your solution works fine! But, note it performs extra work: it trims all values, even though it bails immediately if any are empty. A more performant solution would be `foreach($_POST as $input => $value) { $_POST[$input] = trim($value); if (0 === strlen($_POST[$input])) { throw new Exception('Empty fields detected!'); } }` – bishop Apr 28 '18 at 01:16