Переменные в области видимости условия - PullRequest
1 голос
/ 03 мая 2020

В этом сообществе не так много аргументов в пользу этого аргумента, поэтому я решил оставить этот вопрос.

У меня есть фрагмент кода, используемый для проверки $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'));

Несмотря на $params['full_name"] при правильном заполнении я получаю ошибку во время выполнения:

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

Почему это происходит? Я просто скучаю по теории определения объема внутри if утверждений?

Ответы [ 2 ]

2 голосов
/ 03 мая 2020

Проблема связана с порядком ленивых вычислений, а не сферой. Если вы измените свой && на and, порядок в вашем случае будет изменен, и ваш код будет работать нормально.

В основном правая сторона вашего && имеет приоритет над левой стороной, из-за оператору присваивания слева, и поэтому переменная не существует, когда вычисляется правая сторона. Использование and приведет к тому, что левая сторона сначала оценит, поскольку она имеет более низкий приоритет, чем оператор присваивания, что устраняет проблему.

В качестве отступления. У вас нет кода if в вашем коде. То, что у вас есть, является троичным выражением.

1 голос
/ 03 мая 2020

Этот код не очень удобочитаемый или поддерживаемый. PHP 7 имеет IFFY, поэтому я бы предложил переписать его следующим образом:

$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);

Ваш код можно заставить работать. Проблема заключается в приоритете операций. Оператор && имеет более высокий приоритет, чем оператор присваивания, поэтому в этом случае присваивание $ tmp_name не выполняется до оценки логического &&. Это проиллюстрировано на диаграмме операторов .

. Чтобы сначала выполнить назначение, вам нужно заключить назначение в дополнительный набор символов.

Говоря лично, я не хочу, чтобы мне приходилось кодировать подобные вопросы, если не нужно, но, поскольку вы хотели получить объяснение, вот фиксированная версия:

$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'));
...