Was ist der Unterschied zwischen PHPs print
und echo
?
Stack Overflow hat viele Fragen zur Verwendung von PHP print
und echo
Keywords.
Der Zweck dieses Beitrags besteht darin, eine kanonische Referenzfrage und -antwort zu PHPs print
und echo
Schlüsselwörtern bereitzustellen und deren Unterschiede und Anwendungsfälle zu vergleichen.
Antworten:
Warum zwei Konstrukte?
Die Wahrheit über Druck und Echo ist, dass sie den Benutzern zwar als zwei unterschiedliche Konstrukte erscheinen, aber beide wirklich Echo-Schattierungen sind, wenn Sie sich auf die Grundlagen konzentrieren, dh den internen Quellcode betrachten. Dieser Quellcode umfasst sowohl den Parser als auch die Opcode-Handler. Stellen Sie sich eine einfache Aktion vor, z. B. die Anzeige der Zahl Null. Unabhängig davon, ob Sie Echo oder Print verwenden, wird derselbe Handler "ZEND_ECHO_SPEC_CONST_HANDLER" aufgerufen. Der Handler für den Druck führt eine Aktion aus, bevor er den Handler für das Echo aufruft. Er stellt sicher, dass der Rückgabewert für den Druck wie folgt 1 ist:
(siehe hier als Referenz )
Der Rückgabewert ist eine Annehmlichkeit, wenn Sie print in einem bedingten Ausdruck verwenden möchten. Warum 1 und nicht 100? Nun, in PHP ist die Wahrhaftigkeit von 1 oder 100 dieselbe, dh wahr, während 0 in einem booleschen Kontext einem falschen Wert entspricht. In PHP sind alle Nicht-Null-Werte (positiv und negativ) wahrheitsgemäße Werte, und dies ergibt sich aus dem Perl-Erbe von PHP.
Wenn dies jedoch der Fall ist, kann man sich fragen, warum Echo mehrere Argumente akzeptiert, während print nur eines verarbeiten kann. Für diese Antwort müssen wir uns an den Parser wenden, insbesondere an die Datei zend_language_parser.y . Sie werden feststellen, dass in Echo die Flexibilität eingebaut ist, dass ein oder mehrere Ausdrücke gedruckt werden können (siehe hier ). Während print nur einen Ausdruck drucken darf (siehe dort ).
Syntax
In der Programmiersprache C und von ihr beeinflussten Sprachen wie PHP wird zwischen Anweisungen und Ausdrücken unterschieden. Syntaktisch
echo expr, expr, ... expr
ist eine Anweisung whileprint expr
ein Ausdruck, da sie einen Wert ergibt. Daher steht es wie andere Aussagenecho expr
für sich und kann nicht in einen Ausdruck aufgenommen werden:Im Gegensatz dazu
print expr
kann allein eine Aussage bilden:Oder sei Teil eines Ausdrucks:
Man könnte versucht sein, sich vorzustellen,
print
als wäre es ein unärer Operator, wie!
oder~
aber es ist kein Operator. Was!, ~ and print
gemeinsam haben , ist , dass sie alle in PHP gebaut sind und jeweils nur ein Argument. Sie könnenprint
den folgenden seltsamen, aber gültigen Code erstellen:Auf den ersten Blick kann das Ergebnis seltsam erscheinen , dass der letzte print - Anweisung druckt seine Operanden von ‚7‘ zuerst . Wenn Sie jedoch tiefer graben und sich die tatsächlichen Opcodes ansehen, ist dies sinnvoll:
Der allererste Opcode, der generiert wird, entspricht dem 'print 7'. Die '~ 0' ist eine temporäre Variable mit dem Wert 1. Diese Variable wird zum Operanden für den nächsten Druck-Opcode, der wiederum eine temporäre Variable zurückgibt und den Vorgang wiederholt. Die letzte temporäre Variable wird überhaupt nicht verwendet, sondern freigegeben.
Warum wird
print
ein Wert zurückgegeben undecho
nicht?Ausdrücke werden zu Werten ausgewertet. Zum Beispiel
2 + 3
bewertet zu5
undabs(-10)
bewertet zu10
. Daprint expr
es sich selbst um einen Ausdruck handelt, sollte er einen Wert enthalten, und ein konsistenter Wert von1
zeigt ein wahrheitsgemäßes Ergebnis an. Durch die Rückgabe eines Werts ungleich Null wird der Ausdruck für die Aufnahme in einen anderen Ausdruck nützlich. In diesem Snippet ist beispielsweise der Rückgabewert von print hilfreich, um eine Funktionssequenz zu bestimmen:Möglicherweise finden Sie beim schnellen Debuggen einen Ausdruck von besonderem Wert, wie das nächste Beispiel zeigt:
Als Randnotiz sind Aussagen im Allgemeinen keine Ausdrücke; Sie geben keinen Wert zurück. Die Ausnahme bilden natürlich Ausdrucksanweisungen, die print verwenden, und sogar einfache Ausdrücke, die als Anweisung verwendet werden, z. B.
1;
eine Syntax, die PHP von C erbt. Die Ausdrucksanweisung mag seltsam aussehen, ist jedoch sehr hilfreich und ermöglicht die Übergabe von Argumenten an Funktionen.Ist
print
eine Funktion?Nein, es ist ein Sprachkonstrukt. Während alle Funktionsaufrufe Ausdrücke sind,
print (expr)
handelt es sich trotz der visuellen Darstellung um einen Ausdruck, der so aussieht, als würde die Funktionsaufrufsyntax verwendet. In Wahrheit sind diese Klammern eine Klammern-Ausdruckssyntax, die für die Auswertung von Ausdrücken nützlich ist. Dies erklärt die Tatsache, dass sie manchmal optional sind, wenn der Ausdruck einfach ist, wie zprint "Hello, world!"
. Bei einem komplexeren Ausdruck wieprint (5 ** 2 + 6/2); // 28
den Klammern hilft die Bewertung des Ausdrucks. Im Gegensatz zu Funktionsnamenprint
ist es syntaktisch ein Schlüsselwort und semantisch ein "Sprachkonstrukt" .Der Begriff "Sprachkonstrukt" in PHP bezieht sich normalerweise auf "Pseudo" -Funktionen wie
isset
oderempty
. Obwohl diese "Konstrukte" genau wie Funktionen aussehen, handelt es sich tatsächlich um Fexprs , dh die Argumente werden an sie übergeben, ohne ausgewertet zu werden, was eine besondere Behandlung durch den Compiler erfordert.print
zufällig ein fexpr, der sein Argument auf die gleiche Weise wie eine Funktion bewertet.Der Unterschied ist beim Drucken erkennbar
get_defined_functions()
: Es ist keineprint
Funktion aufgeführt. (Obwohlprintf
und Freunde sind: im Gegensatz zuprint
, sind sie wahre Funktionen.)Warum funktioniert print (foo) dann?
Aus dem gleichen Grund
echo(foo)
funktioniert das. Diese Klammern unterscheiden sich erheblich von Klammern für Funktionsaufrufe, da sie sich stattdessen auf Ausdrücke beziehen. Aus diesem Grund kann man codierenecho ( 5 + 8 )
und erwarten, dass ein Ergebnis von 13 angezeigt wird (siehe Referenz ). Diese Klammern dienen dazu, einen Ausdruck auszuwerten, anstatt eine Funktion aufzurufen. Hinweis: Es gibt andere Verwendungszwecke für Klammern in PHP, z. B. wenn if-bedingte Ausdrücke, Zuweisungslisten, Funktionsdeklarationen usw.Warum
print(1,2,3)
undecho(1,2,3)
führen zu Syntaxfehlern?Die Syntax ist
print expr
,echo expr
oderecho expr, expr, ..., expr
. Wenn PHP auf etwas trifft(1,2,3)
, versucht es, es als einzelnen Ausdruck zu analysieren, und schlägt fehl, da PHP im Gegensatz zu C nicht wirklich über einen binären Kommaoperator verfügt. Das Komma dient eher als Trennzeichen. (Möglicherweise finden Sie dennoch ein binäres Komma in den for-Schleifen von PHP, dessen Syntax von C geerbt wurde.)Semantik
Die Aussage
echo e1, e2, ..., eN;
kann als syntaktischer Zucker für verstanden werdenecho e1; echo e2; ...; echo eN;
.Da alle Ausdrücke Anweisungen sind und
echo e
immer die gleichen Nebenwirkungen haben wieprint e
und der Rückgabewert vonprint e
ignoriert wird, wenn er als Anweisung verwendet wird, können wirecho e
als syntaktischen Zucker für verstehenprint e
.Diese beiden Beobachtungen bedeuten, dass
echo e1, e2, ..., eN;
als syntaktischer Zucker für angesehen werden kannprint e1; print e2; ... print eN;
. (Beachten Sie jedoch die folgenden nicht-semantischen Laufzeitunterschiede.)Wir müssen daher nur die Semantik für definieren
print
.print e
, wenn bewertet:e
und wandelt den resultierenden Wert in eine Zeichenfolge ums
. (Alsoprint e
ist äquivalent zuprint (string) e
.)s
in den Ausgabepuffer (der schließlich in die Standardausgabe gestreamt wird).1
.Unterschiede auf Bytecode-Ebene
print
Das Auffüllen der Rückgabevariablen (Pseudocode) ist mit einem geringen Aufwand verbunden.Single
echo
kompiliert zu einem Opcode:Multi-Value-
echo
Kompilierungen zu mehreren OpcodesBeachten Sie, dass Multi-Value
echo
seine Argumente nicht verkettet, sondern einzeln ausgibt.Referenz:
zend_do_print
,zend_do_echo
.Laufzeitunterschiede
ZEND_PRINT
wird wie folgt implementiert (Pseudocode)Es fügt also
1
im Grunde die Ergebnisvariable ein und delegiert den eigentlichen Job an denZEND_ECHO
Handler.ZEND_ECHO
macht folgendesDabei wird
zend_print_variable()
der eigentliche "Druck" ausgeführt (tatsächlich wird lediglich zu einer dedizierten SAPI-Funktion umgeleitet).Geschwindigkeit:
echo x
vs.print x
Im Gegensatz zu Echo weist print eine temporäre Variable zu. Die für diese Aktivität aufgewendete Zeit ist jedoch winzig, so dass der Unterschied zwischen diesen beiden Sprachkonstrukten vernachlässigbar ist.
Geschwindigkeit:
echo a,b,c
vs.echo a.b.c
Die erste besteht aus drei separaten Anweisungen. Der zweite wertet den gesamten Ausdruck aus
a.b.c.
, druckt das Ergebnis und entsorgt es sofort. Da die Verkettung Speicherzuweisungen und das Kopieren umfasst, ist die erste Option effizienter.Also welches?
In Webanwendungen konzentriert sich die Ausgabe hauptsächlich auf Vorlagen. Da Vorlagen verwendet werden
<?=
, deren Alias dies istecho
, erscheint es logisch, sich auchecho
in anderen Teilen des Codes zu halten.echo
hat den zusätzlichen Vorteil, dass mehrere Ausdrücke gedruckt werden können, ohne sie zu verketten, und es ist kein Aufwand erforderlich, eine temporäre Rückgabevariable zu füllen. Also, benutzeecho
.quelle
echo $a,$b,$c
String-Vars zu verketten? Ich habe das ehrlich gesagt noch nie in Gebrauch gesehen.print
erlaubt nur ein Argument,echo
kann mehrere haben;echo
kann nicht Teil eines Ausdrucks sein, solangeprint
kann und zurückkehrt ...; und kann einige Leistungsübersicht sein. Und all diese "Warum" - und "Unter der Haube"Ich weiß, dass ich zu spät komme, aber eine Sache, die ich hinzufügen möchte, ist die in meinem Code
gibt einen Fehler "Syntaxfehler, unerwartetes 'Echo' (T_ECHO)"
während
funktioniert gut.
Docs über Echo sagt : „Echo ( im Gegensatz zu einigen anderen Sprachkonstrukte) verhält sich nicht wie eine Funktion“ hier aber über den Druck docs sagt auch „Druck nicht tatsächlich eine reelle Funktion ist (es ist ein Sprachkonstrukt)“ hier . Ich bin mir also nicht sicher warum. In Bezug auf Echo und Druckdokumente heißt es: "Die Hauptunterschiede zu Echo bestehen darin, dass der Druck nur ein einziges Argument akzeptiert und immer 1 zurückgibt." Hier
Ich würde mich freuen, wenn jemand etwas Licht in dieses Verhalten bringen kann.
quelle