Intereting Posts
PHP Если оператор всегда срабатывает как истинный preg_replace () заменить второе вхождение как проверить множественную переменную $ _POST для существования с помощью isset ()? Я хочу вставить данные в базу данных mysql, используя PDO PHP. Но данные не вставлены Разница между <? Php?> И <script language = "php"> </ script> Как избежать кавычек при вставке в базу данных с помощью PHP Отключить сообщение об ошибке проверки Yii на фокусе / клавише вверх – Yii2 Почтовая функция PHP не завершает отправку электронной почты Тема WordPress для детей – function.php copy – не может «обновить» Как получить предыдущий год с помощью PHP org.json.JSONException: Значение <br типа java.lang.String не может быть преобразовано в JSONObject Инициатор IPN: «IPN не был отправлен, и рукопожатие не было проверено. Пожалуйста, просмотрите информацию " RHEL + PHP: запись файлов вне / var / www / html? Может ли SQL-инъекция быть предотвращена только с помощью addlashes (string)? file_get_contents с строкой запроса

Скобки, изменяющие семантику результата вызова функции

В другом вопросе было отмечено, что перенос результата вызова функции PHP в круглых скобках может каким-то образом преобразовать результат в полноценное выражение, так что следующее работает:

<?php error_reporting(E_ALL | E_STRICT); function get_array() { return array(); } function foo() { // return reset(get_array()); // ^ error: "Only variables should be passed by reference" return reset((get_array())); // ^ OK } foo(); 

Я пытаюсь найти что-либо в документации, чтобы явно и недвусмысленно объяснить, что здесь происходит. В отличие от C ++, я не знаю достаточно о грамматике PHP и ее обработке высказываний / выражений, чтобы получить ее сам.

Есть ли что-нибудь скрытое в документации относительно этого поведения? Если нет, может ли кто-нибудь объяснить это, не прибегая к предположению?


Обновить

Сначала я нашел этот EBNF , чтобы представить грамматику PHP, и попытался сам расшифровать мои скрипты, но в итоге отказался.

Затем, используя phc для генерации .dot файла двух вариантов foo() , я произвел изображения AST для обоих скриптов, используя следующие команды:

 $ yum install phc graphviz $ phc --dump-ast-dot test1.php > test1.dot $ dot -Tpng test1.dot > test1.png $ phc --dump-ast-dot test2.php > test2.dot $ dot -Tpng test2.dot > test2.png 

В обоих случаях результат был точно таким же:

Разбор дерева фрагментов 1 и 2

Related of "Скобки, изменяющие семантику результата вызова функции"

Такое поведение можно классифицировать как ошибку , поэтому вам определенно не следует полагаться на него.

Условия (упрощенные) для сообщения, которое не нужно бросать на вызов функции, следующие (см. Определение кода операции ZEND_SEND_VAR_NO_REF ):

  • аргумент не является вызовом функции (или если он есть, он возвращается по ссылке) и
  • аргумент является либо ссылкой, либо имеет счетчик ссылок 1 (если у него есть счетчик ссылок 1, он превращается в ссылку).

Давайте проанализируем их более подробно.

Первая точка верна (не вызов функции)

Из-за дополнительных круглых скобок PHP больше не обнаруживает, что аргумент является вызовом функции.

При разборе списка непустых аргументов функции есть три возможности для PHP:

  • expr_without_variable
  • variable
  • (A & за которым следует variable , для удаленной передачи времени по ссылке)

При написании только get_array() PHP видит это как variable .

(get_array()) с другой стороны, не квалифицируется как variable . Это expr_without_variable .

Это в конечном счете влияет на способ компиляции кода, а именно расширенное значение кода операции SEND_VAR_NO_REF больше не будет включать флаг ZEND_ARG_SEND_FUNCTION , который является способом обнаружения функции в реализации кода операции.

Вторая точка верна (счетчик ссылок равен 1)

В нескольких точках Zend Engine позволяет ссылаться на ссылочный счет 1, где ожидаются ссылки. Эти детали не должны подвергаться воздействию пользователя, но, к сожалению, они здесь.

В вашем примере вы возвращаете массив, на который не ссылаются нигде. Если это так, вы все равно получите сообщение, т. Е. Эта вторая точка не будет правдой.

Таким образом, следующий очень похожий пример не работает :

 <?php $a = array(); function get_array() { return $GLOBALS['a']; } return reset((get_array())); 

A) Чтобы понять, что здесь происходит, нужно понимать обработку PHP значений / переменных и ссылок (PDF, 1.2MB). Как указано в документации : «ссылки не являются указателями» ; и вы можете возвращать переменные только по ссылке из функции – ничего больше.

На мой взгляд, это означает, что любая функция в PHP вернет ссылку . Но некоторые функции (встроенные в PHP) требуют значений / переменных в качестве аргументов. Теперь, если вы вставляете функциональные вызовы, внутренний возвращает ссылку, а внешний ожидает значение. Это приводит к «знаменитой» ошибке E_STRICT «Только переменные должны передаваться по ссылке» .

 $fileName = 'example.txt'; $fileExtension = array_pop(explode('.', $fileName)); // will result in Error 2048: Only variables should be passed by reference in… 

B) Я нашел строку в описании синтаксиса PHP, связанную с вопросом .

 expr_without_variable = "(" expr ")" 

В сочетании с этим предложением из документации : «В PHP почти все, что вы пишете, является выражением. Самый простой, но наиболее точный способ определения выражения -« все, что имеет значение ». Это приводит меня к выводу, что даже (5) является выражением в PHP, которое вычисляет целое число со значением 5.

(Поскольку $a = 5 является не только присваиванием, но также выражением, которое вычисляется до 5.)

Вывод

Если вы передадите ссылку на выражение (...) , это выражение вернет значение, которое затем может быть передано как аргумент внешней функции. Если это (моя линия мысли) истинно, следующие две строки должны работать одинаково:

 // what I've used over years: (spaces only added for readability) $fileExtension = array_pop( ( explode('.', $fileName) ) ); // vs $fileExtension = array_pop( $tmp = explode('.', $fileName) ); 

См. Также PHP 5.0.5: Неустранимая ошибка: только переменные могут передаваться по ссылке; 13.09.2005