В чем разница между print
и echo
PHP?
В Stack Overflow есть много вопросов, касающихся использования ключевого слова PHP для print
и echo
.
Цель этого сообщения – предоставить канонический справочный вопрос и ответ на ключевые слова PHP и echo
а также сравнить их различия и варианты использования.
Истина о печати и эхо заключается в том, что, хотя они кажутся пользователям как две разные конструкции, они оба являются оттенками эха, если вы переходите к основам, то есть смотрите на внутренний исходный код. Этот исходный код включает в себя синтаксический анализатор, а также обработчики кода операций. Рассмотрим простое действие, такое как отображение нулевого числа. Будь вы используете эхо или печать, вызывается тот же обработчик «ZEND_ECHO_SPEC_CONST_HANDLER». Обработчик для печати делает одно, прежде чем он вызывает обработчик для эха, он гарантирует, что возвращаемое значение для печати равно 1:
ZVAL_LONG(&EX_T(opline->result.var).tmp_var, 1);
(см. здесь для справки )
Возвращаемое значение – удобство, если вы хотите использовать печать в условном выражении. Почему 1, а не 100? Ну, в PHP правдоподобие 1 или 100 одинаково, т. Е. Истинно, тогда как 0 в булевом контексте эквивалентно ложному значению. В PHP все ненулевые значения (положительные и отрицательные) являются правными значениями, и это происходит из наследия Perl от PHP.
Но если это так, то можно задаться вопросом, почему эхо принимает несколько аргументов, тогда как печать может обрабатывать только один. Для этого ответа нам нужно обратиться к парсеру, в частности к файлу zend_language_parser.y . Вы заметите, что эхо имеет встроенную гибкость, позволяющую печатать одно или несколько выражений (см. Здесь ). тогда как печать ограничивается печатью только одного выражения (см. там ).
На языке программирования C и языках, на которые он воздействует, например на PHP, существует различие между операторами и выражениями. Синтаксически, echo expr, expr, ... expr
– это оператор, в то время как print expr
является выражением, так как оно оценивает значение. Поэтому, как и другие утверждения, echo expr
стоит сам по себе и не может быть включен в выражение:
5 + echo 6; // syntax error
В отличие от этого, print expr
, может самостоятельно формулировать утверждение:
print 5; // valid
Или, быть частью выражения:
$x = (5 + print 5); // 5 var_dump( $x ); // 6
Можно было бы искусить думать о print
как если бы это был унарный оператор, вроде бы !
или ~
однако это не оператор. Что !, ~ and print
имеют то, что все они встроены в PHP, и каждый принимает только один аргумент. Вы можете использовать print
для создания следующего странного, но действительного кода:
<?php print print print print 7; // 7111
На первый взгляд результат может показаться странным, что последний оператор печати сначала печатает свой операнд «7». Но, если вы копаете глубже и смотрите на фактические коды операций, это имеет смысл:
line # * op fetch ext return operands --------------------------------------------------------------------------------- 3 0 > PRINT ~0 7 1 PRINT ~1 ~0 2 PRINT ~2 ~1 3 PRINT ~3 ~2 4 FREE ~3 5 > RETURN 1
Самый первый код операции, который генерируется, соответствует тому, что соответствует «print 7». «~ 0» – временная переменная, значение которой равно 1. Эта переменная становится и операндом для следующего кода операции печати, который, в свою очередь, возвращает временную переменную, и процесс повторяется. Последняя временная переменная не используется вообще, поэтому она освобождается.
print
возвращает значение, а echo
– нет? Выражения оцениваются в значениях. Например, 2 + 3
оценивается до 5
, а abs(-10)
оценивается до 10
. Поскольку print expr
само является выражением, тогда оно должно содержать значение, и это означает, что согласованное значение 1
указывает на правдивый результат и, возвращая ненулевое значение, выражение становится полезным для включения в другое выражение. Например, в этом фрагменте возвращаемое значение печати полезно при определении последовательности функций:
<?php function bar( $baz ) { // other code } function foo() { return print("In and out ...\n"); } if ( foo() ) { bar(); }
Вы можете найти распечатку определенного значения, когда дело доходит до отладки «на лету», как показано в следующем примере:
<?php $haystack = 'abcde'; $needle = 'f'; strpos($haystack,$needle) !== FALSE OR print "$needle not in $haystack"; // output: f not in abcde
Как примечание, как правило, утверждения не являются выражениями; они не возвращают значение. Исключением, конечно, являются выражения, в которых используются печатные и даже простые выражения, используемые в качестве оператора, например 1;
, синтаксис, который PHP наследует от C. Оператор выражения может выглядеть нечетным, но он очень полезен, позволяя передавать аргументы в функции.
print
функции? Нет, это языковая конструкция. Хотя все вызовы функций являются выражениями, print (expr)
является выражением, несмотря на визуальное представление, которое выглядит так, как если бы оно использовало синтаксис вызова функции. По правде говоря, эти скобки являются скобками-синтаксисом expr, полезными для оценки выражения. Это объясняет тот факт, что порой они являются необязательными, если выражение является простым, например print "Hello, world!"
, С более сложным выражением, таким как print (5 ** 2 + 6/2); // 28
print (5 ** 2 + 6/2); // 28
скобки помогают оценить выражение. В отличие от имен функций, синтаксически print
ключевое слово и семантически «языковая конструкция» .
Термин «языковая конструкция» в PHP обычно относится к «псевдо» функциям, таким как isset
или empty
. Хотя эти «конструкции» выглядят точно так же, как функции, они на самом деле являются fexprs , то есть аргументы передаются им без оценки, что требует специальной обработки от компилятора. print
– это fexpr, который выбирает для оценки своего аргумента так же, как функцию.
Разницу можно увидеть путем печати get_defined_functions()
: в списке нет функции print
. (Хотя printf
и друзья: в отличие от print
, они являются истинными функциями.)
По той же причине, что и echo(foo)
. Эти круглые скобки сильно отличаются от круглых скобок вызова функций, поскольку они относятся к выражениям. Вот почему можно запрограммировать echo ( 5 + 8 )
и может ожидать результат 13 для отображения (см. Ссылку ). Эти скобки участвуют в оценке выражения, а не при вызове функции. Примечание. Существуют другие варианты использования скобок в PHP, например if-условные выражения, списки назначений, объявления функций и т. Д.
print(1,2,3)
и echo(1,2,3)
приводят к ошибкам синтаксиса? Синтаксис: print expr
, echo expr
или echo expr, expr, ..., expr
. Когда PHP встречается (1,2,3)
, он пытается разобрать его как одно выражение и терпит неудачу, потому что в отличие от C PHP не имеет бинарного оператора запятой; запятая больше служит разделителем. (Вы можете найти двоичную запятую, тем не менее, в PHP-петлях, синтаксис, который он унаследовал от C.)
Утверждение echo e1, e2, ..., eN;
можно понимать как синтаксический сахар для echo e1; echo e2; ...; echo eN;
echo e1; echo e2; ...; echo eN;
,
Поскольку все выражения являются операторами, а echo e
всегда имеет те же побочные эффекты, что и print e
, а возвращаемое значение print e
игнорируется при использовании в качестве инструкции, мы можем понимать echo e
как синтаксический сахар для print e
.
Эти два наблюдения означают, что echo e1, e2, ..., eN;
можно рассматривать как синтаксический сахар для print e1; print e2; ... print eN;
print e1; print e2; ... print eN;
, (Тем не менее, обратите внимание на не семантические различия во времени выполнения ниже.)
Поэтому нам нужно определить семантику print
. print e
, при оценке:
e
и тип – передает полученное значение в строку s
. (Таким образом, print e
эквивалентно print (string) e
.) s
в выходной буфер (который в конечном итоге будет передаваться на стандартный вывод). 1
. print
включает в себя небольшие накладные расходы при заполнении возвращаемой переменной (псевдокод)
print 125; PRINT 125,$temp ; print 125 and place 1 in $temp UNSET $temp ; remove $temp
одиночное echo
компилируется в один код операции:
echo 125; ECHO 125
многозначное echo
компилируется в несколько кодов операций
echo 123, 456; ECHO 123 ECHO 456
Обратите внимание, что многозначное echo
не объединяет его аргументы, а выводит их по одному.
Ссылка: zend_do_print
, zend_do_echo
.
ZEND_PRINT
реализуется следующим образом (псевдокод)
PRINT var, result: result = 1 ECHO var
Таким образом, он в основном помещает 1
в переменную result и делегирует реальную работу обработчику ZEND_ECHO
. ZEND_ECHO
выполняет следующие
ECHO var: if var is object temp = var->toString() zend_print_variable(temp) else zend_print_variable(var)
где zend_print_variable()
выполняет фактическую «печать» (фактически, она просто перенаправляется на выделенную функцию SAPI).
echo x
vs print x
В отличие от echo , print выделяет временную переменную. Однако время, затраченное на эту деятельность, незначительно, поэтому разница между этими двумя языковыми конструкциями ничтожно мала.
echo a,b,c
vs echo abc
Первый объединяет до трех отдельных операторов. Второе оценивает все выражение abc
, печатает результат и немедленно удаляет его. Поскольку конкатенация включает в себя распределение памяти и копирование, первый вариант будет более эффективным.
В веб-приложениях выход в основном сосредоточен в шаблонах. Поскольку шаблоны используют <?=
, Что является псевдонимом echo
, логично придерживаться echo
в других частях кода. echo
имеет дополнительное преимущество, заключающееся в возможности печати нескольких выражений без их конкатенации и не связано с накладными расходами на временную возвращаемую переменную. Итак, используйте echo
.