Pourquoi deux constructions?
Avoir deux constructions distinctes pour la même chose, c'est à la suite de PHP à la conception moins, foule-driven "naturel" de développement. Je suppose que quelqu'un dans le PHP par l'équipe de travailler beaucoup avec shell UNIX et emprunté echo
, et quelqu'un d'autre a pensé qu'il serait agréable d'avoir de l' print
qui se comporte comme ses Perl homologue.
La syntaxe
Dans les langages procéduraux il y a une distinction entre les déclarations et les expressions. Du point de vue syntaxique, echo e, e, ... e
est un (simple) de l'énoncé, comme break
ou return
. En revanche print e
est une expression. Par conséquent, comme toute autre déclaration, echo e
ne peut pas être une partie d'une expression:
5 + return 6; // syntax error
5 + echo 6; // syntax error
et print e
, tout comme toute autre expression, ne peut à lui seul formulaire de déclaration:
$a = 5; // valid
!5; // valid (but equivalent to a no-op)
print 5; // valid
Bien qu' il n'est pas répertorié en tant que tel, nous pouvons traiter print
comme unaire préfixe de l'opérateur, comme !
ou ~
. Vous pouvez utiliser print
là où l'opérateur préfixe peut être utilisé. Remarque, cela peut obtenir bizarre: print print print print 7
est une expression valide, ce qui s'analyse comme print (print (print (print 7)))
.
Pourquoi est - print
retourner une valeur et echo
ne l'est pas?
Les Expressions doivent correspondre à des valeurs; par exemple !true
évalue false
, et abs(-5)
évalue 5
. Depuis print e
est aussi une expression, il doit correspondre à quelque chose, et puisqu'il n'est utile que pour ses effets secondaires (évaluation e
et l'impression de sa valeur), PHP choisit juste le faire évaluer à une valeur factice. Il a été choisi pour être l'entier 1
.
Les instructions ne peuvent pas faire partie d'une expression et, partant, ne rien retourner.
Est - print
d'une fonction?
Pas de. Alors que tous les appels de fonction sont des expressions, et print (e)
est une expression, et même de la syntaxe ressemble à un appel de fonction, il est néanmoins pas un appel de fonction, et print
n'est pas une fonction. À la différence des noms de fonction, print
est un point de vue syntaxique d'un mot-clé, et de la sémantique d'une "construction du langage".
Le terme de "construction du langage" en PHP se réfère généralement à des "pseudo" fonctionne comme isset
ou empty
. Bien que ces "constructions" exactement comme les fonctions, elles sont en fait fexprs, qui est, les arguments sont passés sans être évalués, ce qui nécessite un traitement spécial du compilateur. print
de passe fexpr qui choisit d'évaluer son argument de la même façon qu'une fonction.
La différence peut être vu par l'impression d' get_defined_functions()
: il n'y a pas d' print
fonction ci. (Si printf
et amis: à la différence de print
, ils sont de véritables fonctions.)
Pourquoi imprimer(foo) fonctionne alors?
Pour la même raison pourquoi -(5 + 4)
travaux. Chaque opérateur peut être appliqué à une sous-expression entre parenthèses. Notez que ces parenthèses sont très différents de l'appel de fonction entre parenthèses, car ils ne permettent pas de virgules à l'intérieur.
Pourquoi dois - print(1,2,3)
et echo(1,2,3)
suite à des erreurs de syntaxe?
La syntaxe est - print expr
, echo expr
ou echo expr, expr, ..., expr
. Lorsque PHP rencontres, (1,2,3)
, il tente de l'analyser comme une simple expression et ne parvient pas, parce que, contrairement au C, la virgule n'est pas un opérateur valide en PHP.
La sémantique
L'énoncé echo e1, e2, ..., eN;
peut être comprise comme un sucre syntaxique pour echo e1; echo e2; ...; echo eN;
.
Depuis toutes ces expressions sont des déclarations, et echo e
a toujours les mêmes effets secondaires comme print e
, et la valeur de retour de l' print e
est ignoré lorsqu'il est utilisé comme une déclaration, nous pouvons le comprendre, echo e
comme sucre syntaxique pour print e
.
Ces deux observations dire qu' echo e1, e2, ..., eN;
peut être vu comme un sucre syntaxique pour print e1; print e2; ... print eN;
. (Notez toutefois que le non-sémantique d'exécution des différences ci-dessous.)
Par conséquent, nous n'avez qu'à définir la sémantique pour l' print
. print e
, lorsqu'elle a été évaluée:
- évalue son seul argument
e
et de type jette la valeur résultante d'une chaîne de caractères s
. (Ainsi, print e
est équivalent à print (string) e
.)
- Les ruisseaux de la chaîne d'
s
de la mémoire tampon de sortie (qui sera finalement diffusé sur la sortie standard).
- Renvoie le nombre entier
1
.
Les différences au niveau du bytecode
print
implique une faible surcharge de remplissage de la variable de retour (pseudo-code)
print 125;
PRINT 125,$temp ; print 125 and place 1 in $temp
UNSET $temp ; remove $temp
seul echo
compile pour un opcode:
echo 125;
ECHO 125
multi-valeur echo
compile de plusieurs opérateurs
echo 123, 456;
ECHO 123
ECHO 456
Notez que multi-valeur echo
n'est pas concaténer ses arguments, mais les sort un par un.
Référence: zend_do_print
, zend_do_echo
.
D'exécution des différences
ZEND_PRINT
est mis en œuvre comme suit (pseudo-code)
PRINT var, result:
result = 1
ECHO var
Donc, essentiellement, il met 1
dans la variable résultat et délègue le travail réel de l' ZEND_ECHO
gestionnaire. ZEND_ECHO
effectue les opérations suivantes
ECHO var:
if var is object
temp = var->toString()
zend_print_variable(temp)
else
zend_print_variable(var)
où zend_print_variable()
effectue le "impression" (en fait, il se contente de les redirige vers un dédié SAPI fonction).
Vitesse: echo x
vs print x
print
déchets de quelque temps, l'allocation d'une variable temporaire, mais ce n'est pas beaucoup, de sorte que la différence sera négligeable.
Vitesse: echo a,b,c
vs echo a.b.c
La première compile trois états distincts. Le deuxième évalue la totalité de l'expression a.b.c.
, imprime le résultat et l'envoie immédiatement. Depuis concaténation consiste à les allocations de mémoire et de la copie, la première option sera plus efficace.
Alors, lequel utiliser?
Dans les applications web, la production est essentiellement concentrée dans les modèles. Depuis les modèles de <?=
, ce qui est l'alias de l' echo
, il semble logique de s'en tenir à echo
dans les autres parties du code. echo
a un avantage supplémentaire d'être en mesure d'imprimer de multiples expression sans la concaténation d'eux et n'implique pas une surcharge de remplissage temporaire de la variable de retour. Ainsi, l'utilisation de echo
.