Apa perbedaan antara PHP print
dan echo
?
Stack Overflow memiliki banyak pertanyaan tentang penggunaan PHP print
dan echo
kata kunci.
Tujuan dari posting ini adalah untuk memberikan pertanyaan dan jawaban referensi kanonik tentang PHP print
dan echo
kata kunci dan membandingkan perbedaan dan kasus penggunaannya.
Jawaban:
Mengapa dua konstruksi?
Kebenaran tentang cetak dan gema adalah bahwa meskipun mereka tampak oleh pengguna sebagai dua konstruksi berbeda, keduanya sama-sama bernuansa gema jika Anda sampai pada dasar-dasarnya, yaitu melihat kode sumber internal. Kode sumber itu melibatkan parser serta penangan opcode. Pertimbangkan tindakan sederhana seperti menampilkan angka nol. Apakah Anda menggunakan gema atau cetak, penangan yang sama "ZEND_ECHO_SPEC_CONST_HANDLER" akan dipanggil. Pawang untuk mencetak melakukan satu hal sebelum memanggil pawang untuk gema, ia memastikan bahwa nilai balik untuk cetakan adalah 1, sebagai berikut:
(lihat di sini untuk referensi )
Nilai baliknya adalah kenyamanan jika seseorang ingin menggunakan cetakan dalam ekspresi bersyarat. Kenapa 1 dan bukan 100? Baik di PHP kebenaran dari 1 atau 100 adalah sama, yaitu benar, sedangkan 0 dalam konteks boolean sama dengan nilai yang salah. Dalam PHP semua nilai bukan nol (positif dan negatif) adalah nilai kebenaran dan ini berasal dari warisan Perl PHP.
Tapi, jika ini masalahnya, maka orang mungkin bertanya-tanya mengapa gema mengambil beberapa argumen sedangkan cetak hanya dapat menangani satu. Untuk jawaban ini kita perlu beralih ke parser, khususnya file zend_language_parser.y . Anda akan mencatat bahwa echo memiliki fleksibilitas bawaan sehingga dapat mencetak satu atau beberapa ekspresi (lihat di sini ). sedangkan cetak dibatasi untuk mencetak hanya satu ekspresi (lihat di sana ).
Sintaksis
Dalam bahasa pemrograman C dan bahasa yang dipengaruhi olehnya seperti PHP, ada perbedaan antara pernyataan dan ekspresi. Secara sintaksis,
echo expr, expr, ... expr
adalah pernyataan sementaraprint expr
adalah ekspresi karena ia mengevaluasi suatu nilai. Oleh karena itu, seperti pernyataan lainnya,echo expr
berdiri sendiri dan tidak mampu dimasukkan dalam ekspresi:Sebaliknya,,
print expr
dapat sendirian membentuk pernyataan:Atau, jadilah bagian dari ekspresi:
Seseorang mungkin tergoda untuk berpikir
print
seolah-olah itu adalah operator yang tidak waspada, seperti!
atau~
bagaimanapun bukan operator. Apa yang!, ~ and print
sama adalah bahwa mereka semua dibangun ke dalam PHP dan masing-masing hanya membutuhkan satu argumen. Anda dapat menggunakanprint
untuk membuat kode aneh tapi valid berikut:Pada pandangan pertama hasilnya mungkin tampak aneh bahwa pernyataan cetak terakhir mencetak operan dari '7' pertama . Tetapi, jika Anda menggali lebih dalam dan melihat opcodes yang sebenarnya masuk akal:
Opcode pertama yang dihasilkan adalah yang sesuai dengan 'print 7'. '~ 0' adalah variabel sementara yang nilainya 1. Variabel itu menjadi dan operan untuk opcode cetak berikutnya yang pada gilirannya mengembalikan variabel sementara dan proses berulang. Variabel sementara terakhir tidak digunakan sama sekali jadi, itu akan dibebaskan.
Mengapa
print
mengembalikan nilai danecho
tidak?Ekspresi mengevaluasi nilai. Misalnya
2 + 3
mengevaluasi ke5
, danabs(-10)
mengevaluasi ke10
. Karenaprint expr
itu sendiri merupakan ekspresi, maka ia harus memiliki nilai dan itu memang, nilai yang konsisten1
menunjukkan hasil yang benar dan dengan mengembalikan nilai yang tidak nol ekspresi menjadi berguna untuk dimasukkan dalam ekspresi lain. Misalnya dalam cuplikan ini, nilai pengembalian cetak berguna dalam menentukan urutan fungsi:Anda mungkin menemukan hasil cetak dengan nilai tertentu ketika melakukan debug dengan cepat, seperti contoh berikut menggambarkan:
Sebagai catatan tambahan, umumnya, pernyataan bukan ekspresi; mereka tidak mengembalikan nilai. Pengecualian, tentu saja adalah pernyataan ekspresi yang menggunakan cetak dan bahkan ekspresi sederhana yang digunakan sebagai pernyataan, seperti
1;
, sintaksis yang diwariskan PHP dari C. Pernyataan ekspresi mungkin terlihat aneh tetapi sangat membantu, sehingga memungkinkan untuk meneruskan argumen ke fungsi.Apakah
print
suatu fungsi?Tidak, ini adalah konstruksi bahasa. Sementara semua panggilan fungsi adalah ekspresi,
print (expr)
adalah ekspresi, meskipun visual yang muncul seolah-olah menggunakan sintaks panggilan fungsi. Sebenarnya tanda kurung ini adalah sintaks tanda kurung-expr, berguna untuk evaluasi ekspresi. Itu menjelaskan fakta bahwa kadang-kadang mereka opsional jika ekspresi itu sederhana, sepertiprint "Hello, world!"
. Dengan ekspresi yang lebih kompleks sepertiprint (5 ** 2 + 6/2); // 28
tanda kurung membantu evaluasi ekspresi. Tidak seperti nama fungsi,print
secara sintaksis kata kunci , dan secara semantik merupakan "konstruksi bahasa" .Istilah "konstruksi bahasa" dalam PHP biasanya merujuk pada fungsi "pseudo" seperti
isset
atauempty
. Meskipun "konstruksi" ini terlihat persis seperti fungsi, mereka sebenarnya adalah fexprs , yaitu argumen yang diteruskan kepada mereka tanpa dievaluasi, yang memerlukan perlakuan khusus dari kompiler.print
kebetulan menjadi fexpr yang memilih untuk mengevaluasi argumennya dengan cara yang sama sebagai fungsi.Perbedaannya dapat dilihat dengan mencetak
get_defined_functions()
: tidak adaprint
fungsi yang terdaftar. (Padahalprintf
dan teman adalah: tidak sepertiprint
, mereka adalah fungsi sebenarnya.)Mengapa print (foo) berfungsi saat itu?
Untuk alasan yang sama itu
echo(foo)
berhasil. Tanda kurung ini sangat berbeda dari tanda kurung fungsi karena mereka berkaitan dengan ekspresi. Itulah sebabnya seseorang dapat mengkodekanecho ( 5 + 8 )
dan dapat mengharapkan hasil 13 untuk ditampilkan (lihat referensi ). Tanda kurung ini terlibat dalam mengevaluasi ekspresi daripada memanggil fungsi. Catatan: ada kegunaan lain untuk tanda kurung di PHP, seperti jika if-conditional expressions, daftar tugas, deklarasi fungsi, dll.Mengapa melakukan
print(1,2,3)
danecho(1,2,3)
menghasilkan kesalahan sintaksis?Sintaksnya adalah
print expr
,echo expr
atauecho expr, expr, ..., expr
. Ketika PHP bertemu(1,2,3)
, ia mencoba untuk menguraikannya sebagai ekspresi tunggal dan gagal, karena tidak seperti C, PHP tidak benar-benar memiliki operator koma biner; koma lebih berfungsi sebagai pemisah. (Anda dapat menemukan koma biner dalam for-loop PHP, sintaksisnya diwarisi dari C.)Semantik
Pernyataan itu
echo e1, e2, ..., eN;
dapat dipahami sebagai gula sintaksis untukecho e1; echo e2; ...; echo eN;
.Karena semua ekspresi adalah pernyataan, dan
echo e
selalu memiliki efek samping yang sama denganprint e
, dan nilai pengembalianprint e
diabaikan ketika digunakan sebagai pernyataan, kita dapat memahamiecho e
sebagai gula sintaksis untukprint e
.Kedua pengamatan ini berarti yang
echo e1, e2, ..., eN;
dapat dilihat sebagai gula sintaksis untukprint e1; print e2; ... print eN;
. (Namun, perhatikan perbedaan runtime non-semantik di bawah ini.)Karena itu kita hanya perlu mendefinisikan semantik untuk
print
.print e
, ketika dievaluasi:e
dan ketik-gips nilai yang dihasilkan ke strings
. (Dengan demikian,print e
setara denganprint (string) e
.)s
ke buffer output (yang akhirnya akan dialirkan ke output standar).1
.Perbedaan pada level bytecode
print
melibatkan overhead kecil untuk mengisi variabel return (pseudocode)echo
kompilasi tunggal ke satu opcode:echo
kompilasi multi-nilai ke beberapa opcodesPerhatikan bahwa multi-nilai
echo
tidak menyatukan argumennya, tetapi mengeluarkannya satu per satu.Referensi:
zend_do_print
,zend_do_echo
.Perbedaan runtime
ZEND_PRINT
diimplementasikan sebagai berikut (pseudocode)Jadi pada dasarnya menempatkan
1
variabel hasil dan mendelegasikan pekerjaan nyata keZEND_ECHO
pawang.ZEND_ECHO
melakukan hal berikutdi mana
zend_print_variable()
melakukan "pencetakan" yang sebenarnya (pada kenyataannya, itu hanya mengalihkan ke fungsi SAPI khusus).Kecepatan:
echo x
vsprint x
Tidak seperti gema , hasil cetak mengalokasikan variabel sementara. Namun, jumlah waktu yang dihabiskan untuk kegiatan ini sangat kecil, sehingga perbedaan antara dua konstruksi bahasa ini dapat diabaikan.
Kecepatan:
echo a,b,c
vsecho a.b.c
Yang pertama dikompilasi menjadi tiga pernyataan terpisah. Yang kedua mengevaluasi seluruh ekspresi
a.b.c.
, mencetak hasilnya dan langsung membuangnya. Karena penggabungan melibatkan alokasi memori dan penyalinan, opsi pertama akan lebih efisien.Jadi yang mana yang harus digunakan?
Dalam aplikasi web, output sebagian besar terkonsentrasi di template. Karena templat digunakan
<?=
, yang merupakan aliasecho
, tampaknya logis untuk tetapecho
di bagian lain dari kode juga.echo
memiliki keuntungan tambahan karena mampu mencetak banyak ekspresi tanpa menggabungkannya dan tidak melibatkan overhead pengisian variabel pengembalian sementara. Jadi, gunakanecho
.sumber
echo $a,$b,$c
untuk penggabungan string vars? Jujur saya tidak pernah melihat ini digunakan.print
memungkinkan hanya satu argumen,echo
mungkin ada banyak;echo
tidak dapat menjadi bagian dari ekspresi selagiprint
bisa dan kembali ...; dan mungkin beberapa ringkasan kinerja. Dan semua bagian "mengapa" dan "di bawah tenda" sesudahnyaSaya tahu saya terlambat tetapi satu hal yang ingin saya tambahkan adalah bahwa dalam kode saya
memberikan kesalahan "kesalahan sintaksis, 'echo' yang tidak terduga (T_ECHO)"
sementara
bekerja dengan baik.
Documents tentang gema mengatakan "gema (tidak seperti beberapa konstruksi bahasa lain) tidak berperilaku seperti fungsi" di sini, tetapi tentang dokumen cetak juga mengatakan "cetak sebenarnya bukan fungsi nyata (ini adalah konstruksi bahasa)" di sini . Jadi saya tidak yakin kenapa. Dan juga tentang gema dan dokumen cetak mengatakan "Perbedaan utama untuk gema adalah bahwa cetak hanya menerima satu argumen dan selalu mengembalikan 1." sini
Saya akan senang jika ada yang bisa menjelaskan perilaku ini.
sumber