Search code examples
phpvalidationif-statementblockscoping

Variables in if condition scope


There's not much about this argument on this community so I thought to drop this question.

I have this piece of code used for validating $params['full_name']:

$params = ["full_name"=>"John Doe"];
$full_name = $flag ? null : ( ( $tmp_name = trim(strip_tags((string)@$params['full_name']))
                            &&  (strlen($tmp_name) > 3 && strlen($tmp_name) < 30)
            ) ? $tmp_name : out('The full name must be 3-30 characters', 'Invalid full name'));

Despite of $params['full_name"] being populated correctly, I get a run-time error:

<b>Notice</b>: Undefined variable: tmp_name

Why is this happening? Am I just missing the theory of scoping inside if statements?


Solution

  • That code isn't very readable or maintainable. PHP 7 has IFFY's so I would suggest rewriting it in this way:

    $full_name = $flag 
        ? null 
        : (function($params) {
             $tmp_name = trim(strip_tags((string)@$params['full_name']));
             return (strlen($tmp_name) > 3 and strlen($tmp_name) < 30)
               ? $tmp_name 
               : out('The full name must be 3-30 characters', 'Invalid full name');
           })($params);
    

    Your code can be made to work. The issue is the precedence of operations. The && operator has a higher precedence than the assignment operator, thus in this circumstance the assignment to $tmp_name is not done prior to the evaluation of the logical &&. This is illustrated in the operators chart.

    To force the assignment to occur first you have to wrap the assignment in an additional set of parens.

    Personally speaking, I don't like to have to code around issues like this if I don't have to, but since you wanted an explanation here's a fixed version:

    $full_name = $flag ? null : ((($tmp_name = trim(strip_tags((string)@$params['full_name'])))
                                &&  (strlen($tmp_name) > 3 && strlen($tmp_name) < 30)) 
                                ? $tmp_name 
                                : out('The full name must be 3-30 characters', 'Invalid full name'));