Почему пустой ожидает T_PAAMAYIM_NEKUDOTAYIM, когда задана не переменная?

<?php
define('foo', 'bar');

if (empty(foo)) {
  echo 'qux';
}

http://codepad.org/G1TSK1c6
Ошибка анализа: синтаксическая ошибка, неожиданный ')', ожидающий T_PAAMAYIM_NEKUDOTAYIM в строке 4

Я знаю, что empty() позволяет передавать переменные только как аргумент, но почему он ожидает T_PAAMAYIM_NEKUDOTAYIM (т.е. ::), когда я даю ему константу?

Ответ 1

Следующая логическая вещь, которую хочет получить парсер, - это ::, потому что foo не является переменной.

if (empty(foo::$bar)) {
}

Это единственное, что работает, когда empty() не передается переменная. Ваш пример оценивается как empty(bar), где парсер принимает bar как имя класса и теперь ожидает статическую переменную-член.

Ответ 2

Пила это, делая некоторые исследования, хотя я знаю, что это удар, я подумал, что я лучше это разъясню.

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

empty() ожидает проверить что-то переменное; константа не является переменной, поэтому она не включена в список возможных синтаксисов, которые могут быть переданы этой конструкции, что имеет прекрасный смысл, поскольку в противном случае вы делали бы что-то нелогичное (проверяя пустоту в постоянном значении).

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

<name>     ::= [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
<variable> ::= $ <name>
<property> ::= <name> :: <name> || $ <name> :: <name> || $ <name> -\> <name>

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

Надеюсь, это было несколько проницательно; -)

Ответ 3

Я посмотрел на это, попробовал это на моей локальной установке PHP и угадал, что? Он работал без сбоев (PHP 5.5.6). После того, как вы попытались использовать тот же код в разных версиях PHP, я обнаружил, что он не работает во всех версиях PHP < 5.5.x и работает иначе.

Итак, я взял в PHP документацию, точнее ее журнал изменений от 5.4.x до 5.5.x, и нашел это:

http://www.php.net/manual/en/migration55.new-features.php#migration55.new-features.empty

empty() поддерживает произвольные выражения

Передача произвольного выражения вместо переменной в empty() теперь поддерживается. Например:

if (empty(TRUE)) {
    echo "This will NOT be printed.\n";
}

if (empty(FALSE)) {
    echo "This will be printed.\n";
}

Вышеприведенный пример выводит:

Это будет напечатано.

Итак, если вы используете PHP >= 5.5.x, это не будет проблемой.

Вы можете протестировать код в разных версиях PHP с помощью этой службы: http://sandbox.onlinephpfunctions.com/. Я не мог, по моей жизни, понять, как сохранить образцы кода (я всегда не получал капчу, хотя он был мертв простым - я думаю, что что-то МОЖЕТ быть разбито на их конце).

Ответ 4

empty() ожидает переменные, а не константы. Вы должны использовать defined() для констант.

Ответ 5

Просто, хотя, но я думаю, что эта ошибка возникает при разборе кода.

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