?: operator ('operator Elvis') di PHP

258

Saya melihat ini hari ini di beberapa kode PHP:

$items = $items ?: $this->_handle->result('next', $this->_result, $this);

Saya tidak terbiasa dengan ?:operator yang digunakan di sini. Sepertinya operator ternary, tetapi ekspresi untuk mengevaluasi apakah predikat itu benar telah dihilangkan. Apa artinya?

alpha_juno
sumber

Jawaban:

529

Mengevaluasi ke operan kiri jika operan kiri adalah truthy , dan operan kanan sebaliknya.

Dalam pseudocode,

foo = bar ?: baz;

secara kasar memutuskan untuk

foo = bar ? bar : baz;

atau

if (bar) {
    foo = bar;
} else {
    foo = baz;
}

dengan perbedaan itu barhanya akan dievaluasi sekali.

Anda juga dapat menggunakan ini untuk melakukan "pemeriksaan sendiri" fooseperti yang ditunjukkan dalam contoh kode yang Anda posting:

foo = foo ?: bar;

Ini akan menetapkan baruntuk foojika foonull atau falsey, yang lain itu akan meninggalkan fooberubah.

Beberapa contoh lagi:

<?php
    var_dump(5 ?: 0); // 5
    var_dump(false ?: 0); // 0
    var_dump(null ?: 'foo'); // 'foo'
    var_dump(true ?: 123); // true
    var_dump('rock' ?: 'roll'); // 'rock'
?>

Omong-omong, itu disebut operator Elvis .

Operator Elvis

BalusC
sumber
11
Pastikan variabel dalam tanda kurung ada, atau Anda akan memunculkan kesalahan. PHP tidak akan hanya menganggapnya memiliki nilai nullatau apa pun. Katakan saja '
DanMan
20
Yang lucu adalah bahwa jawaban ini membentuk loop rekursif dengan artikel Wiki, yang tidak sepenuhnya menjelaskan mengapa itu disebut "operator Elvis".
tampak. Lucu
41
Sedikit operasi, lebih banyak ekspresi.
aalaap
2
Kenapa tidak pakai saja a ||. Jadi blah || 'default'?
Noitidart
10
@Noitidart Karena, tidak seperti di JS di mana ia mengembalikan operan kebenaran paling kiri, dalam PHP ||operator selalu mengembalikan boolean.
ksadowski
58

Lihat dokumen :

Sejak PHP 5.3, dimungkinkan untuk meninggalkan bagian tengah dari operator ternary. Ekspresi expr1 ?: expr3kembali expr1jika expr1dievaluasi ke TRUE, dan expr3sebaliknya.

Yacoby
sumber
10
Mereka membutuhkan penulis dokumen baru karena seseorang pasti akan bertanya apa yang terjadi pada exp2. Saya hanya membuangnya.
John K
7
Apa apaan? Saya baru tahu ini sekarang, tepat setelah memutakhirkan ke PHP 7? Saya bisa menggunakan ini selama bertahun-tahun!
Buttle Butkus
TBH, dokumennya benar. Apa yang terjadi expr2adalah bahwa itu menghilang begitu saja, dan tidak dievaluasi. $this->expensiveComputation() ?: "nope"tidak identik dengan $this->expensiveComputation() ? $this->expensiveComputation() : "nope"- expr1 hanya dievaluasi sekali.
Piskvor meninggalkan gedung
18

Hati-hati dengan array. Kita harus menulis variabel pengecekan setelah ?, karena:

  $params = ['param1' => 'value1',
             'param2' => 'value2',
             'param3' => 'value3',];

  $param1 = isset($params['param1'])?:null;
  $param2 = !empty($params['param2'])?:null;
  $param3 = $params['param3']?:null; // get E_NOTICE, if $params['param3'] eq false

  var_dump($param1,$param2,$param3);
  true // would like to expect `value1`
  true // would like to expect `value2`
  param3 // properly, but problem above

Diperbarui

Dari RFC. Di masa mendatang (dalam PHP 7) operator Null Coalesce Operator akan melakukannya, misalnya:

$param1 = $params['param1'] ?? null;
// Equivalent to:  $param1 = isset($params['param1']) ? $params['param1'] : null;
voodoo417
sumber
1
Ini tidak menjawab pertanyaan, juga tidak berguna bagi siapa pun yang mencoba memahami kapan harus menggunakan Operator Elvis.
Mark Amery
7
@Mark Amery hmm .. Benarkah? Tidak membantu? Apakah Anda benar-benar bekerja dengan PHP dan melihat ribuan kasus dalam menggunakan untuk mengakses vars array dengan ternary? Oke, saya mengubah teks menjadi "Hati-hati dengan array .."
voodoo417
jadi null menyatu dan elvis sama?
Nabeel Khan
7
@NabeelKhan Tidak! Dan itu membuat operator Elvis agak tidak berguna di PHP imo. Operator Elvis mengevaluasi ekspresi dan jika itu benar, ia mengembalikannya jika ia mengembalikan bagian terakhir. Karena PHP diketik dengan rendah, banyak hal akan menjadi benar, atau salah, dan kemungkinan besar hal-hal tidak seperti yang Anda inginkan. Yaitu: Anda ingin menetapkan nilai default ke variabel jika tidak didefinisikan, menggunakan operator Elvis PHP akan mengatakan bahwa 0 tidak didefinisikan, tetapi Anda mungkin ingin 0 ... Itu sebabnya PHP 7 akan mendapatkan operator Null Coalesce , Ini akan benar-benar menguji variabel Anda terhadap nol, sehingga PHP akan mengatakan bahwa 0 tidak terdefinisi.
Gregoire D.
1
@FuscaSoftware: Menggunakan penindasan kesalahan seperti ini bukan ide yang baik dalam pengalaman saya.
TeeHays
8

Pertimbangan penting lainnya: Operator Elvis memecah proses tokenisasi Zend Opcache. Saya menemukan ini dengan cara yang sulit! Sementara ini mungkin telah diperbaiki di versi yang lebih baru, saya dapat mengkonfirmasi masalah ini ada di PHP 5.5.38 (dengan Zend Opcache v7.0.6-dev yang sudah terpasang).

Jika Anda menemukan bahwa beberapa file Anda 'menolak' di-cache di Zend Opcache, ini mungkin salah satu alasannya ... Semoga ini bisa membantu!

Prasad Paradkar
sumber
4

Ya, ini baru dalam PHP 5.3. Ini mengembalikan nilai ekspresi tes jika dievaluasi sebagai BENAR, atau nilai alternatif jika dievaluasi sebagai FALSE.

Atli
sumber
2
Salah / menyesatkan; operan tidak perlu boolean. Yang penting adalah apakah nilai pertama adalah truthy , bukan apakah itu TRUE.
Mark Amery
@MarkAmery Klarifikasi. Seharusnya cukup sulit untuk salah menafsirkannya dengan cara ini.
Atli