Qual é a diferença entre PHP print
e echo
?
O Stack Overflow tem muitas perguntas sobre o uso de PHP print
e echo
palavras - chave.
O objetivo deste post é fornecer uma pergunta de referência canônica e responder sobre PHP print
e echo
palavras-chave e comparar suas diferenças e casos de uso.
Respostas:
Por que duas construções?
A verdade sobre impressão e eco é que, embora eles apareçam para os usuários como duas construções distintas, ambos são realmente tons de eco se você começar o básico, ou seja, observe o código-fonte interno. Esse código fonte envolve o analisador e os manipuladores de código de operação. Considere uma ação simples, como exibir o número zero. Se você usa eco ou impressão, o mesmo manipulador "ZEND_ECHO_SPEC_CONST_HANDLER" será chamado. O manipulador para impressão faz uma coisa antes de chamar o manipulador para eco, garante que o valor de retorno para impressão seja 1, da seguinte maneira:
(veja aqui para referência )
O valor de retorno é uma conveniência, se desejar usar print em uma expressão condicional. Por que 1 e não 100? Bem, no PHP, a veracidade de 1 ou 100 é a mesma, ou seja, verdadeira, enquanto 0 em um contexto booleano equivale a um valor falso. No PHP, todos os valores diferentes de zero (positivo e negativo) são verdadeiros e isso deriva do legado Perl do PHP.
Mas, se esse for o caso, pode-se perguntar por que o eco aceita vários argumentos, enquanto a impressão pode apenas lidar com um. Para esta resposta, precisamos recorrer ao analisador, especificamente ao arquivo zend_language_parser.y . Você observará que o eco tem a flexibilidade incorporada para que possa imprimir uma ou várias expressões (veja aqui ). enquanto a impressão é restrita a imprimir apenas uma expressão (veja lá ).
Sintaxe
Na linguagem de programação C e nas linguagens influenciadas por ele, como PHP, há uma distinção entre instruções e expressões. Sintaticamente,
echo expr, expr, ... expr
é uma declaração enquantoprint expr
é uma expressão, pois é avaliada como um valor. Portanto, como outras declarações,echo expr
é independente e é incapaz de incluir em uma expressão:Por outro lado,
print expr
sozinho pode formar uma declaração:Ou faça parte de uma expressão:
Pode-se ficar tentado a pensar
print
como se fosse um operador unário, como!
ou~
no entanto não é um operador. O que!, ~ and print
tem em comum é que todos eles estão embutidos no PHP e cada um leva apenas um argumento. Você pode usarprint
para criar o seguinte código estranho, mas válido:À primeira vista, o resultado pode parecer estranho que a última declaração de impressão imprime seu operando de '7' primeiro . Mas, se você se aprofundar e observar os opcodes reais, faz sentido:
O primeiro opcode gerado é o correspondente ao 'print 7'. O '~ 0' é uma variável temporária cujo valor é 1. Essa variável se torna e operando para o próximo código de operação de impressão que, por sua vez, retorna uma variável temporária e o processo se repete. A última variável temporária não é usada, portanto, é liberada.
Por que
print
retornar um valor eecho
não?Expressões avaliadas em valores. Por exemplo,
2 + 3
é avaliada como5
, eabs(-10)
avalia a10
. Comoprint expr
ela própria é uma expressão, ela deve conter um valor, e isso significa, um valor consistente1
indica um resultado verdadeiro e, ao retornar um valor diferente de zero, a expressão se torna útil para inclusão em outra expressão. Por exemplo, neste trecho, o valor de retorno de impressão é útil para determinar uma sequência de funções:Você pode encontrar uma impressão de valor específico quando se trata de depuração em tempo real, como o próximo exemplo ilustra:
Como uma nota lateral, geralmente, declarações não são expressões; eles não retornam um valor. A exceção, é claro, são declarações de expressão que usam expressões impressas e até simples usadas como declaração, como
1;
uma sintaxe que o PHP herda de C. A declaração de expressão pode parecer estranha, mas é muito útil, possibilitando passar argumentos para funções.É
print
uma função?Não, é uma construção de linguagem. Embora todas as chamadas de função sejam expressões,
print (expr)
é uma expressão, apesar do visual que aparece como se estivesse usando a sintaxe da chamada de função. Na verdade, esses parênteses são parênteses-expr, úteis para avaliação de expressões. Isso explica o fato de que às vezes eles são opcionais se a expressão for simples, comoprint "Hello, world!"
. Com uma expressão mais complexa, comoprint (5 ** 2 + 6/2); // 28
parênteses, ajuda na avaliação da expressão. Diferentemente dos nomes das funções,print
é sintaticamente uma palavra-chave e semanticamente uma "construção de linguagem" .O termo "construção de linguagem" no PHP geralmente se refere a funções "pseudo" como
isset
ouempty
. Embora essas "construções" pareçam exatamente com funções, elas são na verdade fexprs , ou seja, os argumentos são passados para elas sem serem avaliadas, o que requer tratamento especial do compilador.print
passa a ser um fexpr que escolhe avaliar seu argumento da mesma maneira que uma função.A diferença pode ser vista na impressão
get_defined_functions()
: não há nenhumaprint
função listada. (Emboraprintf
e amigos sejam: ao contrárioprint
, são verdadeiras funções.)Por que a impressão (foo) funciona então?
Pela mesma razão que
echo(foo)
funciona. Esses parênteses são bem diferentes dos parênteses das chamadas de função porque, em vez disso, pertencem a expressões. É por isso que se pode codificarecho ( 5 + 8 )
e esperar que um resultado 13 seja exibido (consulte a referência ). Esses parênteses estão envolvidos na avaliação de uma expressão, em vez de invocar uma função. Nota: existem outros usos para parênteses no PHP, como expressões if-condicionais, listas de atribuições, declarações de funções, etc.Por que
print(1,2,3)
eecho(1,2,3)
resultar em erros de sintaxe?A sintaxe é
print expr
,echo expr
ouecho expr, expr, ..., expr
. Quando o PHP encontra(1,2,3)
, ele tenta analisá-lo como uma única expressão e falha, porque, diferentemente de C, o PHP realmente não possui um operador de vírgula binária; a vírgula serve mais como separador. (Você pode encontrar uma vírgula binária, no entanto, nos for-loops do PHP, sintaxe herdada de C.)Semântica
A afirmação
echo e1, e2, ..., eN;
pode ser entendida como açúcar sintático paraecho e1; echo e2; ...; echo eN;
.Como todas as expressões são declarações, e
echo e
sempre tem os mesmos efeitos colaterais queprint e
, e o valor de retorno deprint e
é ignorado quando usado como uma declaração, podemos entenderecho e
como açúcar sintático paraprint e
.Essas duas observações significam que
echo e1, e2, ..., eN;
pode ser visto como açúcar sintático paraprint e1; print e2; ... print eN;
. (No entanto, observe as diferenças de tempo de execução não semânticas abaixo.)Portanto, só precisamos definir a semântica para
print
.print e
, quando avaliado:e
e converte o valor resultante em uma strings
. (Assim,print e
é equivalente aprint (string) e
.)s
para o buffer de saída (que eventualmente será transmitido para a saída padrão).1
.Diferenças no nível do bytecode
print
envolve uma pequena sobrecarga de preenchimento da variável de retorno (pseudocódigo)echo
compilações únicas em um código de operação:echo
compilações de vários valores em vários opcodesObserve que o valor múltiplo
echo
não concatena seus argumentos, mas os gera um por um.Referência:
zend_do_print
,zend_do_echo
.Diferenças de tempo de execução
ZEND_PRINT
é implementado da seguinte forma (pseudocódigo)Portanto, basicamente coloca
1
a variável result e delega o trabalho real aoZEND_ECHO
manipulador.ZEND_ECHO
faz o seguinteonde
zend_print_variable()
realiza a "impressão" real (na verdade, apenas redireciona para uma função SAPI dedicada).Velocidade:
echo x
vsprint x
Ao contrário do eco , a impressão aloca uma variável temporária. No entanto, a quantidade de tempo gasto nessa atividade é minúscula; portanto, a diferença entre essas duas construções de linguagem é insignificante.
Velocidade:
echo a,b,c
vsecho a.b.c
O primeiro compila até três instruções separadas. O segundo avalia a expressão inteira
a.b.c.
, imprime o resultado e o descarta imediatamente. Como a concatenação envolve alocações de memória e cópia, a primeira opção será mais eficiente.Então, qual usar?
Em aplicativos da Web, a saída é concentrada principalmente em modelos. Como os modelos usam
<?=
, que é o apelido deecho
, também parece lógico manterecho
outras partes do código.echo
possui uma vantagem adicional de poder imprimir várias expressões sem concatená-las e não envolve a sobrecarga de preencher uma variável de retorno temporária. Então, useecho
.fonte
echo $a,$b,$c
para concatenação de vars de string? Sinceramente, nunca vi isso em uso.print
permite apenas um argumento,echo
pode ter múltiplos;echo
não pode fazer parte de uma expressão enquantoprint
pode e retorna ...; e pode haver algum resumo de desempenho. E todos aqueles "por que" e "sob o capô" seSei que estou atrasado, mas uma coisa que gostaria de acrescentar é que no meu código
dá um erro "erro de sintaxe, 'eco' inesperado (T_ECHO)"
enquanto
funciona bem.
Os documentos sobre eco dizem que "eco (diferente de outras construções de linguagem) não se comporta como uma função" aqui, mas sobre os documentos impressos também diz "impressão não é realmente uma função real (é uma construção de linguagem)" aqui . Então, eu não sei por que. E também sobre documentos de eco e impressão, diz: "As principais diferenças de eco são que a impressão aceita apenas um único argumento e sempre retorna 1". aqui
Ficaria feliz se alguém pudesse lançar alguma luz sobre esse comportamento.
fonte