?: ตัวดำเนินการ (ตัวดำเนินการ 'Elvis') ใน PHP


258

ฉันเห็นสิ่งนี้วันนี้ในรหัส PHP บางส่วน:

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

ฉันไม่คุ้นเคยกับ?:โอเปอร์เรเตอร์ที่ใช้ที่นี่ ดูเหมือนว่าผู้ประกอบการที่สาม แต่การแสดงออกในการประเมินว่าภาคที่เป็นจริงได้รับการละเว้น มันหมายความว่าอะไร?

คำตอบ:


529

มันจะถูกประเมินเป็นตัวถูกดำเนินการทางซ้ายถ้าตัวถูกดำเนินการด้านซ้ายเป็นความจริงและตัวถูกดำเนินการด้านขวาเป็นอย่างอื่น

ใน pseudocode

foo = bar ?: baz;

คร่าวๆ

foo = bar ? bar : baz;

หรือ

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

ด้วยความแตกต่างที่barจะได้รับการประเมินเพียงครั้งเดียว

นอกจากนี้คุณยังสามารถใช้สิ่งนี้เพื่อทำการ "ตรวจสอบตัวเอง" ของfooที่แสดงในตัวอย่างรหัสที่คุณโพสต์:

foo = foo ?: bar;

สิ่งนี้จะกำหนดbarให้fooถ้าfooเป็นโมฆะหรือเท็จมิฉะนั้นจะfooไม่มีการเปลี่ยนแปลง

ตัวอย่างเพิ่มเติม:

<?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'
?>

โดยวิธีการที่มันเรียกว่าผู้ประกอบการเอลวิส

ผู้ประกอบการ Elvis


11
ตรวจสอบให้แน่ใจว่ามีตัวแปรในวงเล็บอยู่หรือไม่หรือคุณกำลังจะเกิดข้อผิดพลาด PHP จะไม่เพียง แต่คิดว่ามันมีค่าnullหรืออะไร เพียงแค่ว่า '
DanMan

20
มีอะไรที่ตลกคือคำตอบนี้ก่อให้เกิดวนซ้ำกับบทความ Wiki ซึ่งไม่ได้อธิบายอย่างเต็มที่ว่าเหตุใดจึงเรียกว่า "ผู้ดำเนินการ Elvis"
seeming.use

41
การใช้งานน้อยลงนิดหน่อยโปรดแสดงความคิดเห็นเพิ่มเติม
aalaap

2
||ทำไมไม่เพียงแค่ใช้ งั้นblah || 'default'เหรอ?
Noitidart

10
@Noitidart เพราะแตกต่างจากใน JS ที่จะส่งกลับตัวถูกดำเนินการจริงซ้ายสุดใน PHP ||ผู้ประกอบการมักจะส่งกลับบูลีน
ksadowski

58

ดูเอกสาร :

ตั้งแต่ PHP 5.3 เป็นไปได้ที่จะปล่อยให้ผู้ประกอบการกลางส่วนที่สามออกมา นิพจน์expr1 ?: expr3ส่งคืนexpr1ถ้าexpr1ประเมินค่าเป็นTRUE, และexpr3อื่น ๆ


10
พวกเขาต้องการนักเขียนเอกสารคนใหม่เพราะมีคนถามว่าเกิดอะไรขึ้นกับ expr2 อย่างหลีกเลี่ยงไม่ได้ ฉันแค่โยนมันทิ้ง
John K

7
ห่า? ฉันเพิ่งพบสิ่งนี้ทันทีหลังจากอัพเกรดเป็น PHP 7? ฉันน่าจะใช้สิ่งนี้มาหลายปีแล้ว!
Buttle Butkus

TBH เอกสารนั้นถูกต้อง สิ่งที่เกิดขึ้นexpr2คือมันเพิ่งหายไปและไม่ได้รับการประเมิน $this->expensiveComputation() ?: "nope"ไม่เหมือนกัน$this->expensiveComputation() ? $this->expensiveComputation() : "nope"- expr1 จะถูกประเมินเพียงครั้งเดียว
Piskvor ออกจากอาคาร

18

ระวังด้วยอาร์เรย์ เราจะต้องเขียนตัวแปรตรวจสอบหลังจาก?เพราะ:

  $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

Updated

จาก RFC ในอนาคตตัวดำเนินการ (ใน PHP 7) Null Coalesce Operatorจะดำเนินการเช่น:

$param1 = $params['param1'] ?? null;
// Equivalent to:  $param1 = isset($params['param1']) ? $params['param1'] : null;

1
สิ่งนี้ไม่ตอบคำถามและไม่มีประโยชน์สำหรับใครก็ตามที่พยายามเข้าใจว่าจะใช้ Elvis Operator เมื่อใด
Mark Amery

7
@ Mark Amery hmm .. จริงเหรอ? ไม่เป็นประโยชน์ใช่ไหม คุณทำงานกับ PHP จริงๆและดูหลายพันกรณีในการใช้ vars ของอาร์เรย์ด้วยไตรภาคหรือไม่? ตกลงฉันเปลี่ยนข้อความเป็น "ระวังอาร์เรย์ ... "
voodoo417

null จะรวมตัวกันและ elvis เหมือนกันหรือไม่
Nabeel Khan

7
@NabeelKhan ไม่! และนั่นทำให้ตัวดำเนินการ Elvis ไร้ประโยชน์ใน PHP imo ผู้ประกอบการ Elvis ประเมินการแสดงออกและถ้ามันเป็นความจริงก็จะส่งกลับอีกส่วนหนึ่งมันกลับส่วนสุดท้าย เนื่องจาก PHP พิมพ์น้อยสิ่งต่างๆมากมายจะเป็นจริงหรือไม่จริงและสิ่งที่น่าเป็นไปได้ส่วนใหญ่จะไม่ใช่สิ่งที่คุณต้องการ เช่น: คุณต้องการตั้งค่าเริ่มต้นเป็นตัวแปรหากไม่ได้กำหนดไว้การใช้ตัวดำเนินการ Elvis PHP จะบอกว่า 0 ไม่ได้ถูกกำหนด แต่คุณอาจต้องการที่ 0 ... นั่นคือสาเหตุที่ PHP 7 จะได้ตัวดำเนินการ Null Coalesce มันจะทดสอบตัวแปรของคุณกับค่า null อย่างเคร่งครัดดังนั้น PHP จะบอกว่า 0 ไม่ได้ถูกกำหนด
Gregoire D.

1
@FuscaSoftware: การใช้การระงับข้อผิดพลาดเช่นนี้ไม่ใช่ความคิดที่ดีในประสบการณ์ของฉัน
TeeHays

8

การพิจารณาที่สำคัญอีกประการหนึ่ง: Elvis Operator แบ่งกระบวนการโทเค็น Zend Opcache ฉันพบสิ่งนี้เป็นวิธีที่ยาก! แม้ว่าสิ่งนี้อาจได้รับการแก้ไขในรุ่นที่ใหม่กว่า แต่ฉันสามารถยืนยันได้ว่าปัญหานี้มีอยู่ใน PHP 5.5.38 (ด้วย Zend Opcache v7.0.6-dev ในตัว)

หากคุณพบว่าไฟล์ 'ปฏิเสธ' บางไฟล์ของคุณถูกแคชใน Zend Opcache นี่อาจเป็นหนึ่งในสาเหตุ ... หวังว่านี่จะช่วยได้!


4

ใช่นี่เป็นของใหม่ใน PHP 5.3 มันจะส่งกลับค่าของนิพจน์ทดสอบหากมีการประเมินว่าเป็น TRUE หรือค่าทางเลือกหากมีการประเมินเป็น FALSE


2
ผิด / เข้าใจผิดอย่างละเอียด ตัวถูกดำเนินการไม่จำเป็นต้องเป็นบูลีน สิ่งที่สำคัญคือไม่ว่าจะเป็นค่าแรกtruthyTRUEไม่ว่าจะเป็น
Mark Amery

@MarkAmery ชี้แจงแล้ว ควรตีความยากด้วยวิธีนี้
Atli
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.