?: toán tử ('toán tử Elvis') trong PHP


258

Tôi đã thấy điều này ngày hôm nay trong một số mã PHP:

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

Tôi không quen thuộc với các ?:nhà điều hành đang được sử dụng ở đây. Nó trông giống như một toán tử ternary, nhưng biểu thức để đánh giá nếu vị ngữ là đúng đã bị bỏ qua. Nó có nghĩa là gì?

Câu trả lời:


529

Nó đánh giá toán hạng bên trái nếu toán hạng bên trái là trung thực và toán hạng bên phải khác.

Trong mã giả,

foo = bar ?: baz;

đại khái giải quyết

foo = bar ? bar : baz;

hoặc là

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

với sự khác biệt barsẽ chỉ được đánh giá một lần.

Bạn cũng có thể sử dụng điều này để thực hiện "tự kiểm tra" foonhư thể hiện trong ví dụ mã bạn đã đăng:

foo = foo ?: bar;

Điều này sẽ gán barcho foonếu foolà null hoặc falsey, nếu không nó sẽ fookhông thay đổi.

Một số ví dụ khác:

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

Nhân tiện, nó được gọi là toán tử Elvis .

Toán tử Elvis


11
Hãy chắc chắn rằng biến trong ngoặc đơn tồn tại hoặc bạn sẽ đưa ra lỗi. PHP sẽ không chỉ cho rằng nó có giá trị nullhoặc bất cứ thứ gì. Chỉ cần nói
Danman

20
Điều thú vị là câu trả lời này tạo thành một vòng lặp đệ quy với bài viết Wiki, điều này không giải thích đầy đủ lý do tại sao nó được gọi là "toán tử Elvis".
dường như.amuses

41
Một chút ít hoạt động, một chút biểu hiện xin vui lòng.
aalaap

2
Tại sao không chỉ sử dụng a ||. Vậy blah || 'default'sao
Noitidart

10
@Noitidart Bởi vì, không giống như trong JS nơi nó trả về toán hạng trung thực ngoài cùng bên trái, trong PHP ||toán tử luôn trả về một boolean.
ksadowski

58

Xem tài liệu :

Kể từ PHP 5.3, có thể loại bỏ phần giữa của toán tử ternary. Biểu thức expr1 ?: expr3trả về expr1nếu expr1đánh giá TRUE, và expr3nếu không.


10
Họ cần một người viết tài liệu mới vì chắc chắn sẽ có người hỏi chuyện gì đã xảy ra với expr2. Tôi chỉ thunk nó.
John K

7
Cái quái gì thế Tôi chỉ tìm thấy điều này ngay bây giờ, ngay sau khi nâng cấp lên PHP 7? Tôi có thể đã sử dụng điều này trong nhiều năm!
Butussy Butkus

TBH, các tài liệu là chính xác. Điều gì đã xảy ra expr2là nó chỉ biến mất và không được đánh giá. $this->expensiveComputation() ?: "nope"không giống với $this->expensiveComputation() ? $this->expensiveComputation() : "nope"- expr1 chỉ được đánh giá một lần.
Piskvor rời khỏi tòa nhà

18

Hãy cẩn thận với mảng. Chúng ta phải viết một biến kiểm tra sau ?, bởi vì:

  $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

Đã cập nhật

Từ RFC. Trong tương lai (trong PHP 7) toán tử Null Coalesce Toán tử sẽ làm điều đó, ví dụ:

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

1
Điều này không trả lời câu hỏi, cũng không hữu ích cho bất kỳ ai đang cố gắng hiểu khi nào nên sử dụng Toán tử Elvis.
Mark Amery

7
@Mark Amery hmm .. Thật sao? Có hữu ích không? Bạn đã thực sự làm việc với PHP và xem xét hàng ngàn trường hợp trong việc sử dụng để truy cập các vars của mảng với ternary? Ok, tôi đã thay đổi văn bản thành "Cẩn thận với mảng .."
voodoo417

vì vậy null hợp nhất và elvis là như nhau?
Nabeel Khan

7
@NabeelKhan Không! Và điều đó làm cho toán tử Elvis trở nên vô dụng trong PHP imo. Toán tử Elvis đánh giá một biểu thức và nếu nó đúng, nó trả về nó một biểu thức khác, nó trả về phần cuối cùng. Vì PHP được gõ thấp nên nhiều thứ sẽ đúng hoặc sai và rất có thể mọi thứ sẽ không như bạn muốn. Tức là: Bạn muốn đặt một giá trị mặc định thành một biến nếu nó không được xác định, sử dụng toán tử Elvis PHP sẽ nói rằng 0 không được xác định, nhưng bạn có thể muốn 0 ... Đó là lý do tại sao PHP 7 sẽ có toán tử Null Coalesce , Nó sẽ kiểm tra nghiêm ngặt biến của bạn với null, vì vậy PHP sẽ nói rằng 0 không được xác định.
Gregoire D.

1
@FuscaSoftware: Sử dụng loại bỏ lỗi như thế này không phải là một ý tưởng tốt trong kinh nghiệm của tôi.
TeeHays

8

Một cân nhắc quan trọng khác: Nhà điều hành Elvis phá vỡ quy trình mã hóa Zend Opcache. Tôi thấy điều này một cách khó khăn! Mặc dù điều này có thể đã được sửa trong các phiên bản sau, tôi có thể xác nhận sự cố này tồn tại trong PHP 5.5,38 (với Zend Opcache v7.0.6-dev được xây dựng).

Nếu bạn thấy rằng một số tệp của mình 'từ chối' được lưu trong bộ nhớ cache trong Zend Opcache, đây có thể là một trong những lý do ... Hy vọng điều này sẽ giúp!


4

Vâng, đây là cái mới trong PHP 5.3. Nó trả về giá trị của biểu thức kiểm tra nếu nó được đánh giá là TRUE hoặc giá trị thay thế nếu nó được đánh giá là FALSE.


2
Khéo léo / sai lệch; không toán hạng cần phải là một boolean. Điều đáng quan tâm là liệu giá trị đầu tiên là truthy , không cho dù đó là TRUE.
Mark Amery

@MarkAmery Làm rõ. Nên khá khó để giải thích sai theo cách này.
Atli
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.