выполнение Почему в PHP работает «or die()», а «or return»-нет?




php exit (3)

Я хочу поблагодарить вас за этот вопрос, так как я понятия не имел, что вы не можете выполнить or return в PHP. Я был так же удивлен, как и вы, когда я проверял это. Этот вопрос дал мне хорошее оправдание, чтобы провести некоторое исследование и поиграть во внутренностях PHP, что было довольно забавно. Тем не менее, я не эксперт по внутренним компонентам PHP, поэтому ниже приведен взгляд непрофессионала на внутренние компоненты PHP, хотя я думаю, что он довольно точный.

or return не работает, потому что синтаксический анализатор языка не return как «выражение».

Ключевое слово or определяется в языке PHP как токен с именем T_LOGICAL_OR , и единственное выражение, в котором оно определено, выглядит следующим this :

 expr T_LOGICAL_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }

Не беспокойтесь о битах в фигурных скобках - это просто определяет, как обрабатывается фактическая логика «или». То, что у вас осталось, это expr T_LOGICAL_OR expr , который просто говорит, что это допустимое выражение с выражением, за которым T_LOGICAL_OR токен T_LOGICAL_OR , за которым следует другое выражение.

expr также определяется синтаксическим анализатором, как и следовало ожидать. Это может быть либо r_variable , которая просто означает, что это переменная, которую вам разрешено читать, либо expr_without_variable , которая является причудливым способом сказать, что выражение может быть сделано из других выражений.

Вы можете сделать or die() потому что языковая конструкция die (не функция!) И его exit псевдонима представлены токеном T_EXIT , а T_EXIT считается допустимым expr_without_variable , тогда как оператор return - токен T_RETURN - нет.

Теперь, почему T_EXIT считается выражением, а T_RETURN - нет? Честно говоря, я понятия не имею. Может быть, это был просто выбор дизайна, сделанный просто для того, чтобы позволить конструкции or die() о которой вы спрашиваете. Тот факт, что раньше он широко использовался - по крайней мере, в таких вещах, как учебные пособия, поскольку я не могу говорить с большим объемом производственного кода - кажется, подразумевает, что это мог быть преднамеренный выбор. Вы должны были бы попросить разработчиков языка знать наверняка.

С учетом всего сказанного это не должно иметь значения. Хотя конструкция or die() выглядела повсеместно в учебниках (см. Выше) несколько лет назад, на самом деле это не рекомендуется, так как это пример «умного кода». or die() не является собственной конструкцией, а скорее фокусом, который использует - некоторые могут сказать злоупотребления - два побочных эффекта оператора or :

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

Некоторые люди считают, что подобная хитрость является неблагоприятной, поскольку программисту сложнее читать, но при этом экономится всего несколько символов в исходном коде. Поскольку время программиста дорого, а дисковое пространство дешево, вы можете понять, почему людям это не нравится.

Вместо этого вы должны четко заявить о своих намерениях, расширив код до полноценного оператора if :

$handle = fopen($location, "r");
if ($handle) {
  // process the file
} else {
  return 0;
}

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

if ($handle = fopen($location, "r")) {
  // process the file
} else {
  return 0;
}

И последнее: принято считать, что возврат 0 в качестве кода состояния указывает на успех, поэтому вы, вероятно, захотите вернуть другое значение, чтобы указать, что вы не можете открыть файл.

В PHP вы можете обрабатывать ошибки, вызывая or die чтобы выйти, когда вы сталкиваетесь с определенными ошибками, например так:

$handle = fopen($location, "r") or die("Couldn't get handle");

Использование die() не является отличным способом обработки ошибок. Я бы предпочел вернуть код ошибки, чтобы родительская функция могла решить, что делать, вместо того, чтобы просто завершить сценарий некорректно и отобразить ошибку пользователю.

Тем не менее, PHP показывает ошибку, когда я пытаюсь заменить or die or return , как это:

$handle = fopen($location, "r") or return 0;

Почему or die() работает, а не or return 0 ?


Answer #1

Я тоже наткнулся на это однажды. Все, что я мог найти, было это:

https://bugs.php.net/bug.php?id=40712

Посмотрите на комментарий внизу:

это не ошибка

Я искал в документации, и я думаю, что это связано с тем, что return 0 является оператором, тогда как die() по сути является выражением. Вы не можете запустить $handle = return 0; но $handle = fun(); действительный код

Что касается обработки ошибок, я бы порекомендовал пользовательские коды или использование пользовательских обработчиков и триггеров. Последние описаны здесь, например.


Answer #2

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

if(1==1) return();  // say what??

Если бы это было так, return должен был бы быть функцией, которая выполняет «двойной выход», оставляя не только свою собственную область, но и область вызова. Поэтому return - это не что иное, как выражение, оно просто не может работать таким образом.

Теперь теоретически return может быть выражением, которое оценивает (скажем) как false, а затем выходит из функции; возможно, более поздняя версия PHP будет реализовывать это.

То же самое относится к goto, который был бы шармом, чтобы работать как запасной вариант; и да, запасные варианты необходимы и часто делают код читабельным, поэтому, если кто-то жалуется на «умный код» (что, безусловно, является хорошим аргументом), возможно, у php должен быть какой-то «официальный» способ сделать такую ​​вещь:

connectMyDB() fallback return false;

Что-то вроде попробовать ... поймать, просто ближе к делу. И лично я был бы намного счастлив, если бы «или» выполнял эту работу, поскольку она хорошо работает с грамматикой английского языка: «соединение или сообщение об ошибке».

TLDR: ты абсолютно прав: возвращайся, переходи, ломайся - ни один из них не работает. Легко понять почему, но все же раздражает.





parse-error