Referans: PHP'nin baskı ve yankısını karşılaştırma


182

PHP printve arasındaki fark nedir echo?

Stack Overflow PHP printve echoanahtar kelime kullanımı hakkında birçok soru soruyor .

Bu yazının amacı, PHP'ler ve anahtar kelimeler hakkında kanonik bir referans sorusu ve yanıtı sağlamak ve farklılıklarını ve kullanım durumlarını karşılaştırmaktır.printecho


3
Burada baskı geri dönüş değeri hakkında yeterli olmadığını düşünüyorum. Yazdırma, hızlı hata ayıklama çıktısı veya bunun gibi bir şey için kullanışlıdır: strpos ($ x, $ y)! == YANLIŞ VEYA "bir şey" yazdırın. Hızlı yazılır ve okunması iyidir. Ve "bir fonksiyon yazdırmak" herhangi bir nedenden dolayı okumak garipti (argümanlarınız ... garip ve açık değil) - dil yapısı, onunla yapamayacağınız çok daha kötü bir şey var: değişken fonksiyonlar.
XzKto

1
Bunu açık tutmak için burada yapılması gerekenler: 1. bir soru ve cevaba bölün. 2. Yığın Taşması konusundaki ( yanıt burada olduğu gibi: stackoverflow.com/questions/3737139/… ) ancak yanıttaki konu hakkındaki mevcut içeriğe referans / bağlantı . 3. CW olması gerekir.
Kev

"İlgili Sütun" iyidir, ancak çok odaklanmış değildir. Kanonik bir referans sorusu ve cevabı olarak değerini artırmak için de iyi araştırılmalı ve diğer spesifik iyi cevaplara bağlantılar değer katacaktır.
Kev

Sorunun gerçekten gerçek bir soru olması gerekiyor . İşiniz bittiğinde kanonik bölümle ilgili bir afiş ekleyebilirim.
Tim Post

Yanıtlar:


185

Neden iki yapı?

Baskı ve yankı hakkındaki gerçek , kullanıcılara iki farklı yapı olarak görünseler de, temellere inerseniz, yani dahili kaynak koduna baktığınızda, her ikisi de gerçekten yankı tonlarıdır. Bu kaynak kodu ayrıştırıcıyı ve opcode işleyicilerini içerir. Sıfır sayısını görüntülemek gibi basit bir işlemi düşünün. Yankı veya baskı kullansanız da, aynı işleyici "ZEND_ECHO_SPEC_CONST_HANDLER" çağrılır. Yazdırma işleyicisi yankı için işleyiciyi çağırmadan önce bir şey yapar, yazdırma için dönüş değerinin aşağıdaki gibi 1 olduğundan emin olur:

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

( referans için buraya bakınız )

Dönüş değeri, koşullu ifadede baskıyı kullanmak isteyen bir kolaylıktır. Neden 1 değil 100? PHP'de 1 veya 100'ün doğruluğu aynıdır, yani doğrudur, oysa boolean bağlamında 0 yanlış bir değere eşittir. PHP'de sıfır olmayan tüm değerler (pozitif ve negatif) gerçeğe uygun değerlerdir ve bu PHP'nin Perl mirasından kaynaklanır.

Ancak, eğer durum buysa, o zaman echo neden birden fazla argüman alırken, baskı sadece bir tanesini işleyebilir. Bu cevap için ayrıştırıcıya, özellikle de zend_language_parser.y dosyasına dönmemiz gerekiyor . Echo'nun bir veya daha fazla ifade yazabilmesi için yerleşik esnekliğe sahip olduğunu göreceksiniz ( buraya bakın ). oysa baskı yalnızca bir ifade basmaya sınırlıdır ( oraya bakınız ).

Sözdizimi

C programlama dilinde ve PHP gibi etkilenen dillerde, ifadeler ve ifadeler arasında bir ayrım vardır. Sözdizimsel olarak, bir değer olarak değerlendirildiği için echo expr, expr, ... exprwhile print exprifadesidir. Bu nedenle, diğer ifadeler gibi echo expr, kendi başına durur ve bir ifadeye dahil edilemez:

5 + echo 6;   // syntax error

Aksine, print exprtek başına bir ifade oluşturabilir:

print 5; // valid

Veya bir ifadenin parçası olun:

   $x = (5 + print 5); // 5 
   var_dump( $x );     // 6 

Kişi print, sanki bir operatör gibi !ya da ~bir operatör gibi düşünülmeyebilir . Ne !, ~ and printortak noktası hepsinin PHP yerleşik olarak ve her tek bir argüman alır olmasıdır. printAşağıdaki garip ama geçerli kodu oluşturmak için kullanabilirsiniz :

    <?php 
    print print print print 7; // 7111

İlk bakışta sonuç, son baskı ifadesinin ilk olarak '7' operandını yazdırması tuhaf görünebilir . Ancak, daha derine iner ve gerçek opcode bakarsanız, mantıklı:

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

Üretilen ilk opcode 'baskı 7'ye karşılık gelen koddur. '~ 0' değeri 1 olan geçici bir değişkendir. Bu değişken bir sonraki yazdırma opkodu için olur ve işlenir, bu da geçici bir değişken döndürür ve işlem tekrarlanır. Son geçici değişken hiç kullanılmaz, bu yüzden serbest kalır.

Neden printbir değer döndürüyor ve echovermiyor?

İfadeler değerlere göre değerlendirilir. Örneğin , 2 + 3değerini 5ve abs(-10)değerini değerlendirir 10. Bu yana print exprbir ekspresyon kendisi, o zaman bir değer sahip olmalıdır ve bu, tutarlı bir değeri de 1bir truthy sonucunu gösterir ve ifade bir ifade dahil edilmesi için yararlı olur, sıfır olmayan bir değer iade ile. Örneğin bu snippet'te, baskının dönüş değeri bir işlev sırası belirlemede yararlıdır:

<?php

function bar( $baz ) { 
   // other code   
}
function foo() {
  return print("In and out ...\n");
}

if ( foo() ) {

     bar();
}

Sonraki örnekte gösterildiği gibi, hata ayıklama söz konusu olduğunda belirli bir değerin baskısını bulabilirsiniz:

<?php
$haystack = 'abcde';
$needle = 'f';
strpos($haystack,$needle) !== FALSE OR print "$needle not in $haystack"; 

// output: f not in abcde

Bir yan not olarak, genellikle ifadeler ifade değildir; bir değer döndürmezler. İstisna, elbette, 1;PHP'yi C'den devraldığı bir sözdizimi gibi baskı ve hatta ifade olarak kullanılan basit ifadeleri kullanan ifade ifadeleridir. İfade ifadesi tuhaf görünebilir, ancak argümanları iletmeyi mümkün kılar. fonksiyonlar.

printbir işlev?

Hayır, bir dil kurgusu. Tüm işlev çağrıları ifadeler print (expr)olsa da, işlev çağrısı sözdizimi kullanıyormuş gibi görünen görsele rağmen bir ifadedir. Gerçekte bu parantezler, ifade değerlendirmesi için yararlı olan parantez-ifade sözdizimidir. Bu, ifadenin basit bir ifadesi olduğu durumlarda zaman zaman isteğe bağlı oldukları gerçeğini açıklar print "Hello, world!". print (5 ** 2 + 6/2); // 28Parantez gibi daha karmaşık bir ifade ile ifadenin değerlendirilmesine yardımcı olur. İşlev adlarının aksine print, sözdizimsel olarak bir anahtar kelime ve anlamsal olarak bir "dil yapısı" dır .

PHP'deki "dil yapısı" terimi genellikle issetveya gibi "sözde" işlevlere karşılık gelir empty. Bu "yapılar" tam olarak işlevler gibi görünseler de , gerçekte feksprlerdir , yani argümanlar değerlendirilmeden onlara aktarılır, bu da derleyiciden özel bir işlem gerektirir. printargümanını bir işlevle aynı şekilde değerlendirmeyi seçen bir fekspr olur.

Fark yazdırılarak görülebilir get_defined_functions(): printlistelenen işlev yok . (Rağmen printfve arkadaşlar: aksine print, onlar gerçek işlevler.)

O halde baskı (foo) neden çalışır?

Aynı nedenden dolayı echo(foo)çalışır. Bu parantezler işlev çağrısı parantezlerinden oldukça farklıdır, çünkü bunun yerine ifadelerle ilgilidirler. Bu yüzden kodlama echo ( 5 + 8 )yapılabilir ve 13 sonucunun görüntülenmesini bekleyebilir ( referansa bakın ). Bu parantez, bir işlevi çağırmak yerine bir ifadeyi değerlendirmekle ilgilidir. Not: PHP'de parantez için if-koşullu ifadeler, atama listeleri, işlev bildirimleri vb. Gibi başka kullanımlar da vardır.

Neden print(1,2,3)ve echo(1,2,3)sözdizimi hatalarına neden?

Sözdizimi print expr, echo exprya echo expr, expr, ..., expr. PHP karşılaştığında (1,2,3), bunu tek bir ifade olarak ayrıştırmaya çalışır ve başarısız olur, çünkü C'nin aksine, PHP'nin gerçekten bir ikili virgül operatörü yoktur; virgül daha çok ayırıcı görevi görür. (Yine de PHP'nin döngülerinde ikili bir virgül bulabilirsiniz, sözdizimi C'den miras alınmıştır)

semantik

İfadesi echo e1, e2, ..., eN;için sözdizimsel şeker gibi anlaşılabilir echo e1; echo e2; ...; echo eN;.

Tüm ifadeler ifadeler olduğundan ve echo eher zaman aynı yan etkilere sahip print eolduğundan ve print eifadesi olarak kullanıldığında dönüş değeri göz ardı edildiğinden echo esözdizimsel şeker olarak anlayabiliriz print e.

Bu iki gözlem echo e1, e2, ..., eN;, sözdizimsel şeker olarak görülebileceği anlamına gelir print e1; print e2; ... print eN;. (Ancak, aşağıda semantik olmayan çalışma zamanı farklılıklarına dikkat edin.)

Bu nedenle, sadece semantiği tanımlamamız gerekir print. print e, değerlendirildiğinde:

  1. Bunu tek bir bağımsız değişken değerlendirir eve tip-atan bir dizi elde edilen değer s. (Böylece, print eeşdeğerdir print (string) e.)
  2. Dizeyi Akımlar siçin çıkış tamponu (sonunda standart çıkışa akışı yayınlanmayacaktır).
  3. Tamsayıyı değerlendirir 1.

Bayt kodu düzeyindeki farklılıklar

print dönüş değişkenini doldurmanın küçük bir ek yükünü içerir (sözde kod)

print 125;

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

tek echobir opcode derler:

echo 125;

ECHO 125

çok değerli echoçoklu kodları derler

echo 123, 456;

ECHO 123
ECHO 456

Çoklu değerin echobağımsız değişkenlerini birleştirmediğini, ancak bunları teker teker çıkardığını unutmayın .

Referans: zend_do_print, zend_do_echo.

Çalışma zamanı farklılıkları

ZEND_PRINT aşağıdaki gibi uygulanır (sözde kod)

PRINT  var, result:

    result = 1
    ECHO var

Temelde 1sonuç değişkenini koyar ve gerçek işi ZEND_ECHOişleyiciye devreder . ZEND_ECHOaşağıdakileri yapar

ECHO var:

    if var is object
        temp = var->toString()
        zend_print_variable(temp)
    else
        zend_print_variable(var)

burada zend_print_variable()gerçek "yazdırma" işlevini gerçekleştirir (aslında yalnızca özel bir SAPI işlevine yönlendirir).

Hız: echo xvsprint x

Aksine yankı , baskı geçici bir değişken ayırır. Bununla birlikte, bu etkinlik için harcanan zaman çok küçüktür, bu nedenle bu iki dil yapısı arasındaki fark göz ardı edilebilir.

Hız: echo a,b,cvsecho a.b.c

İlki üç ayrı ifadeyi derler. İkincisi tüm ifadeyi değerlendirir, a.b.c.sonucu yazdırır ve hemen atar. Birleştirme bellek ayırmalarını ve kopyalamayı içerdiğinden, ilk seçenek daha verimli olacaktır.

Peki hangisini kullanmalıyım?

Web uygulamalarında, çıktı çoğunlukla şablonlarda yoğunlaşır. Şablonlar <?=, takma adı olan kullandığından , kodun diğer kısımlarına da bağlı kalmak echomantıklı görünüyor echo. echobirden çok ifadeyi birleştirmeden yazdırabilmesinin ek bir avantajı vardır ve geçici bir dönüş değişkenini doldurma yükünü içermez. Yani, kullanın echo.


5
Bunu kapsamlı bir şekilde düzenledim ve açıkladım ve anlambilim üzerine bir bölüm ekledim. Buna oldukça eminim, ama birisi bunu iki kez kontrol edebilirdi.
jameshfisher

1
Öyleyse bu echo $a,$b,$c, string değişkenlerinin birleştirilmesi için kullanmanın daha iyi olduğu anlamına mı geliyor ? Dürüst olmak gerekirse bu kullanımda hiç görmedim.
geoff

1
Fonksiyonel farklılıkları tanımlayan TL; DR bölümüne ne dersiniz? Gibi: printsadece bir argüman izin verir, echobirden fazla olabilir; echocan printve return ifadesinin bir parçası olamaz ...; ve bazı performans özetleri olabilir. Ve sonra tüm bu "neden" ve "kaputun altında" parçalar
YakovL

0

Geç olduğumu biliyorum ama eklemek istediğim bir şey kodumda

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

"sözdizimi hatası, beklenmeyen 'echo' (T_ECHO)" hatası veriyor

süre

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

iyi çalışıyor.

Yankı hakkında Dokümanlar "bir işlev gibi davranmaz (diğer dil oluşumlarından farklı olarak) echo" diyor burada da "baskı aslında bir işlev değildir (bir dil oluşumudur) değil" diyor ama baskı dokümanlar hakkında burada . Bu yüzden neden olduğundan emin değilim. Ayrıca yankı ve basılı dokümanlar hakkında da "Yankıdaki en büyük fark, baskının yalnızca tek bir argümanı kabul etmesi ve her zaman 1 döndürmesi." buraya

Herkes bu davranış hakkında biraz ışık tutabilseydi mutlu olurum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.