Ссылка: Сравнение печати PHP и эха - PullRequest
177 голосов
/ 17 августа 2011

В чем разница между PHP print и echo?

Переполнение стека содержит много вопросов об использовании ключевых слов PHP print и echo.

Цель этого поста - предоставить канонический справочник вопросов и ответов о ключевых словах PHP print и echo и сравнить их различия и варианты использования.

Ответы [ 2 ]

181 голосов
/ 17 августа 2011

Почему две конструкции?

Правда о print и echo заключается в том, что, хотя они представляются пользователям как две отдельные конструкции, они действительно являются оттенками эхаесли вы приступите к основам, то есть посмотрите на внутренний исходный код.Этот исходный код включает в себя как синтаксический анализатор, так и обработчики кода операции.Рассмотрим простое действие, такое как отображение числа ноль.Используете ли вы echo или print, будет вызываться один и тот же обработчик "ZEND_ECHO_SPEC_CONST_HANDLER".Обработчик для печати делает одну вещь, прежде чем он вызывает обработчик для эха, он гарантирует, что возвращаемое значение для печати равно 1, следующим образом:

ZVAL_LONG(&EX_T(opline->result.var).tmp_var, 1);

(см. здесь для ссылки )

Возвращаемое значение удобно, если вы хотите использовать print в условном выражении.Почему 1, а не 100?В PHP истинность 1 или 100 одинакова, то есть истинна, тогда как 0 в логическом контексте приравнивается к ложному значению.В PHP все ненулевые значения (положительные и отрицательные) являются истинными значениями, и это вытекает из наследства PHP в Perl.

Но, если это так, то можно задаться вопросом, почему echo принимает несколько аргументов, тогда как print может обрабатывать только один.Для этого ответа нам нужно обратиться к парсеру, а именно к файлу zend_language_parser.y .Вы заметите, что в echo встроена гибкость, позволяющая печатать одно или несколько выражений (см. здесь ).в то время как печать ограничена печатью только одного выражения (см. там ).

Синтаксис

В языке программирования 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

На первый взгляд результат может показаться странным, что последний оператор print печатает свой операнд '7' first .Но если вы копаете глубже и смотрите на действительные коды операций, это имеет смысл:

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 указывает на достоверный результат, и, возвращая ненулевое значение, выражение становится полезным для включения в другое выражение.Например, в этом фрагменте возвращаемое значение print полезно при определении последовательности функций:

<?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

Как примечание, как правило, заявления не являются выражениями;они не возвращают значение.Исключением, конечно, являются операторы выражений, которые используют print и даже простые выражения, используемые в качестве операторов, такие как 1;, синтаксис, который PHP наследует от C. Оператор выражения может выглядеть странно, но он очень полезен, позволяяпередавать аргументы в функции.

Является ли print функцией?

Нет, это языковая конструкция. Хотя все вызовы функций являются выражениями, print (expr) является выражением, несмотря на то, что визуальный элемент выглядит так, как если бы он использовал синтаксис вызова функций. По правде говоря, эти скобки представляют собой синтаксис скобок-expr, полезный для вычисления выражений. Это объясняет тот факт, что иногда они являются необязательными, если выражение является простым, например print "Hello, world!". С более сложным выражением, таким как print (5 ** 2 + 6/2); // 28, круглые скобки помогают оценить выражение. В отличие от имен функций, print является синтаксически ключевым словом , а семантически "языковой конструкцией" .

Термин «языковая конструкция» в PHP обычно относится к «псевдо» функциям, таким как isset или empty. Хотя эти «конструкции» выглядят в точности как функции, на самом деле они fexprs , то есть аргументы передаются им без оценки, что требует особой обработки от компилятора. print оказывается fexpr, который выбирает оценку своего аргумента так же, как и функцию.

Разницу можно увидеть, напечатав get_defined_functions(): в списке нет функции print. (Хотя printf и друзья: в отличие от print, они являются настоящими функциями.)

Почему тогда работает print (foo)?

По той же причине, что 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 на самом деле не имеет двоичного оператора запятой; запятая служит в качестве разделителя. (Тем не менее, вы можете найти двоичную запятую в циклах for PHP, синтаксис которой унаследован от C.)

Семантика

Утверждение echo e1, e2, ..., 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. print e, при оценке:

  1. оценивает свой единственный аргумент e и приводит к типу результирующее значение в строку s. (Таким образом, print e эквивалентно print (string) e.)
  2. Потоковая строка s в выходной буфер (который в конечном итоге будет передаваться на стандартный вывод).
  3. Оценивает целое число 1.

Различия на уровне байт-кода

print включает небольшие накладные расходы на заполнение возвращаемой переменной (псевдокод)

print 125;

PRINT  125,$temp     ; print 125 and place 1 in $temp 
UNSET  $temp         ; remove $temp

single 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 в переменную результата и делегирует реальную работу обработчику 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 против print x

В отличие от echo , print выделяет временную переменную. Тем не менее, количество времени, затрачиваемого на эту деятельность, ничтожно, поэтому разница между этими двумя языковыми конструкциями незначительна.

Скорость: echo a,b,c против echo a.b.c

Первый сводится к трем отдельным утверждениям. Второе вычисляет все выражение a.b.c., печатает результат и немедленно удаляет его. Поскольку объединение включает в себя выделение памяти и копирование, первый вариант будет более эффективным.

Так какой же использовать?

В веб-приложениях вывод в основном сконцентрирован в шаблонах. Поскольку шаблоны используют <?=, который является псевдонимом echo, кажется логичным придерживаться echo и в других частях кода. echo имеет дополнительное преимущество, заключающееся в возможности печатать несколько выражений без их конкатенации и не требует дополнительных затрат на заполнение временной возвращаемой переменной. Итак, используйте echo.

0 голосов
/ 02 мая 2019

Я знаю, что опоздал, но я хотел бы добавить, что в моем коде

 $stmt = mysqli_stmt_init($connection) or echo "error at init"; 

выдает ошибку «синтаксическая ошибка, неожиданное« эхо »(T_ECHO)»

пока

 $stmt = mysqli_stmt_init($connection) or print "error at init";

работает нормально.

В документах об эхо сказано, что "эхо (в отличие от некоторых других языковых конструкций) не ведет себя как функция" здесь , но о документах печати также говорится "печать на самом деле не является реальной функцией (этоязыковая конструкция) " здесь .Поэтому я не уверен, почему.В документах echo и print также говорится: «Основные отличия echo в том, что print принимает только один аргумент и всегда возвращает 1». здесь

Я был бы счастлив, если бы кто-нибудь смог пролить свет на это поведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...