¿Cuál es la diferencia entre PHP print
y echo
?
Stack Overflow tiene muchas preguntas sobre PHP print
y el echo
uso de palabras clave.
El propósito de esta publicación es proporcionar una pregunta y respuesta de referencia canónica sobre PHP print
y echo
palabras clave y comparar sus diferencias y casos de uso.
Respuestas:
¿Por qué dos construcciones?
La verdad acerca de la impresión y el eco es que, si bien los usuarios los ven como dos construcciones distintas, ambos son realmente sombras de eco si se llega a lo básico, es decir, mire el código fuente interno. Ese código fuente involucra tanto el analizador como los manejadores de código de operación. Considere una acción simple como mostrar el número cero. Ya sea que use echo o print, se invocará el mismo controlador "ZEND_ECHO_SPEC_CONST_HANDLER". El controlador para imprimir hace una cosa antes de invocar al controlador para echo, se asegura de que el valor de retorno para print sea 1, de la siguiente manera:
(ver aquí para referencia )
El valor de retorno es conveniente si se desea utilizar print en una expresión condicional. ¿Por qué 1 y no 100? Bueno, en PHP, la veracidad de 1 o 100 es la misma, es decir, verdadera, mientras que 0 en un contexto booleano equivale a un valor falso. En PHP, todos los valores distintos de cero (positivo y negativo) son valores verdaderos y esto se deriva del legado de Perl de PHP.
Pero, si este es el caso, entonces uno puede preguntarse por qué echo toma múltiples argumentos mientras que print solo puede manejar uno. Para esta respuesta, debemos recurrir al analizador, específicamente al archivo zend_language_parser.y . Notarás que echo tiene la flexibilidad incorporada para que pueda imprimir una o varias expresiones (ver aquí ). mientras que print se limita a imprimir solo una expresión (ver allí ).
Sintaxis
En el lenguaje de programación C y los lenguajes influenciados por él, como PHP, hay una distinción entre declaraciones y expresiones. Sintácticamente,
echo expr, expr, ... expr
es una declaración, mientras queprint expr
es una expresión, ya que se evalúa como un valor. Por lo tanto, como otras declaraciones, seecho expr
sostiene por sí solo y es incapaz de ser incluido en una expresión:Por el contrario,
print expr
solo puede formar una declaración:O ser parte de una expresión:
Uno podría sentirse tentado a pensar
print
que se trata de un operador unario, como!
o~
no es un operador. Lo que!, ~ and print
tienen en común es que todos están integrados en PHP y cada uno toma solo un argumento. Puede usarprint
para crear el siguiente código extraño pero válido:A primera vista, el resultado puede parecer extraño que la última declaración de impresión imprima primero su operando de '7' . Pero, si profundiza y mira los códigos de operación reales, tiene sentido:
El primer código de operación que se genera es el correspondiente a la 'impresión 7'. El '~ 0' es una variable temporal cuyo valor es 1. Esa variable se convierte y operando para el siguiente código de operación de impresión que a su vez devuelve una variable temporal y el proceso se repite. La última variable temporal no se usa en absoluto, por lo que se libera.
¿Por qué
print
devuelve un valor yecho
no lo hace?Las expresiones evalúan los valores. Por ejemplo
2 + 3
evalúa a5
, yabs(-10)
se evalúa como10
. Dado queprint expr
es en sí misma una expresión, entonces debe contener un valor y lo hace, un valor consistente de1
indica un resultado verdadero y al devolver un valor distinto de cero la expresión se vuelve útil para su inclusión en otra expresión. Por ejemplo, en este fragmento, el valor de retorno de print es útil para determinar una secuencia de funciones:Puede encontrar impresiones de un valor particular cuando se trata de depurar sobre la marcha, como lo ilustra el siguiente ejemplo:
Como nota al margen, en general, las declaraciones no son expresiones; No devuelven un valor. La excepción, por supuesto, son las declaraciones de expresión que usan expresiones impresas e incluso simples usadas como una declaración, como
1;
una sintaxis que PHP hereda de C. La declaración de expresión puede parecer extraña pero es muy útil, ya que permite pasar argumentos a funcionesEs
print
una función?No, es una construcción de lenguaje. Si bien todas las llamadas a funciones son expresiones,
print (expr)
es una expresión, a pesar de lo visual que aparece como si estuviera usando la sintaxis de llamadas a funciones. En verdad, estos paréntesis son sintaxis paréntesis-expr, útiles para la evaluación de expresiones. Eso explica el hecho de que a veces son opcionales si la expresión es simple, comoprint "Hello, world!"
. Con una expresión más compleja, comoprint (5 ** 2 + 6/2); // 28
los paréntesis, ayuda a evaluar la expresión. A diferencia de los nombres de funciones,print
es sintácticamente una palabra clave y semánticamente una "construcción de lenguaje" .El término "construcción de lenguaje" en PHP generalmente se refiere a funciones "pseudo" como
isset
oempty
. Aunque estas "construcciones" se ven exactamente como funciones, en realidad son fexprs , es decir, los argumentos se les pasan sin ser evaluados, lo que requiere un tratamiento especial del compilador.print
resulta ser un fexpr que elige evaluar su argumento de la misma manera que una función.La diferencia se puede ver imprimiendo
get_defined_functions()
: no hay ningunaprint
función en la lista. (Aunque losprintf
amigos son: a diferenciaprint
, son funciones verdaderas).¿Por qué funciona print (foo) entonces?
Por la misma razón que
echo(foo)
funciona. Estos paréntesis son bastante diferentes de los paréntesis de llamadas a funciones porque pertenecen a expresiones en su lugar. Es por eso que uno puede codificarecho ( 5 + 8 )
y esperar que se muestre un resultado de 13 (ver referencia ). Estos paréntesis están involucrados en la evaluación de una expresión en lugar de invocar una función. Nota: hay otros usos para paréntesis en PHP, como expresiones if-conditional, listas de asignación, declaraciones de funciones, etc.¿Por qué hacer
print(1,2,3)
yecho(1,2,3)
dar lugar a errores de sintaxis?La sintaxis es
print expr
,echo expr
oecho expr, expr, ..., expr
. Cuando PHP se encuentra(1,2,3)
, intenta analizarlo como una sola expresión y falla, porque a diferencia de C, PHP realmente no tiene un operador de coma binario; la coma sirve más como separador. (No obstante, puede encontrar una coma binaria en los bucles for de PHP, sintaxis que heredó de C.)Semántica
La declaración
echo e1, e2, ..., eN;
puede entenderse como azúcar sintáctica paraecho e1; echo e2; ...; echo eN;
.Como todas las expresiones son declaraciones y
echo e
siempre tienen los mismos efectos secundarios queprint e
, y el valor de retorno deprint e
se ignora cuando se usa como una declaración, podemos entenderloecho e
como azúcar sintáctica paraprint e
.Estas dos observaciones significan que
echo e1, e2, ..., eN;
puede verse como azúcar sintáctica paraprint e1; print e2; ... print eN;
. (Sin embargo, tenga en cuenta las diferencias de tiempo de ejecución no semánticas a continuación).Por lo tanto, solo tenemos que definir la semántica para
print
.print e
, cuando se evalúa:e
y convierte el valor resultante en una cadenas
. (Por lo tanto,print e
es equivalente aprint (string) e
).s
al búfer de salida (que eventualmente se transmitirá a la salida estándar).1
.Diferencias a nivel de bytecode
print
implica una pequeña sobrecarga de poblar la variable de retorno (pseudocódigo)echo
compilaciones individuales en un código de operación:echo
compilaciones de múltiples valores para múltiples códigos de operaciónTenga en cuenta que el valor múltiple
echo
no concatena sus argumentos, sino que los genera uno por uno.Referencia:
zend_do_print
,zend_do_echo
.Diferencias de tiempo de ejecución
ZEND_PRINT
se implementa de la siguiente manera (pseudocódigo)Por lo tanto, básicamente coloca
1
la variable de resultado y delega el trabajo real alZEND_ECHO
controlador.ZEND_ECHO
hace lo siguientedonde
zend_print_variable()
realiza la "impresión" real (de hecho, simplemente redirige a una función SAPI dedicada).Velocidad:
echo x
vsprint x
A diferencia de echo , print asigna una variable temporal. Sin embargo, la cantidad de tiempo dedicado a esta actividad es minúscula, por lo que la diferencia entre estas dos construcciones de lenguaje es insignificante.
Velocidad:
echo a,b,c
vsecho a.b.c
El primero se resume en tres declaraciones separadas. El segundo evalúa la expresión completa.
a.b.c.
, imprime el resultado y lo elimina de inmediato. Dado que la concatenación implica asignaciones de memoria y copia, la primera opción será más eficiente.Entonces, ¿cuál usar?
En aplicaciones web, la salida se concentra principalmente en plantillas. Dado que las plantillas usan
<?=
, que es el alias deecho
, parece lógico seguirecho
en otras partes del código también.echo
tiene una ventaja adicional de poder imprimir múltiples expresiones sin concatenarlas y no implica una sobrecarga de llenar una variable de retorno temporal. Entonces, useecho
.fuente
echo $a,$b,$c
para la concatenación de cadenas vars? Sinceramente, nunca he visto esto en uso.print
permite solo un argumento,echo
puede tener múltiples;echo
no puede ser parte de una expresión mientrasprint
can y devuelve ...; y puede haber algún resumen de rendimiento. Y todas esas partes de "por qué" y "bajo el capó" despuésSé que llego tarde, pero una cosa que me gustaría agregar es que en mi código
da un error "error de sintaxis, 'eco' inesperado (T_ECHO)"
mientras
funciona bien.
Los documentos sobre echo dicen "echo (a diferencia de otras construcciones de lenguaje) no se comporta como una función" aquí, pero acerca de print docs también dice "print no es realmente una función real (es una construcción de lenguaje)" aquí . Entonces no estoy seguro de por qué. Y también sobre echo e print docs dice "Las principales diferencias con echo son que print solo acepta un argumento y siempre devuelve 1". aquí
Sería feliz si alguien puede arrojar algo de luz sobre este comportamiento.
fuente