Câu trả lời:
Khi đối số đầu tiên của bạn là null, về cơ bản chúng giống nhau ngoại trừ việc kết hợp null sẽ không xuất ra E_NOTICE
khi bạn có một biến không xác định. Các tài liệu di chuyển PHP 7.0 có điều này để nói:
Toán tử hợp nhất null (??) đã được thêm vào dưới dạng đường cú pháp cho trường hợp phổ biến là cần sử dụng một ternary kết hợp với isset (). Nó trả về toán hạng đầu tiên của nó nếu nó tồn tại và không phải là NULL; nếu không, nó trả về toán hạng thứ hai của nó.
Dưới đây là một số mã ví dụ để chứng minh điều này:
<?php
$a = null;
print $a ?? 'b'; // b
print "\n";
print $a ?: 'b'; // b
print "\n";
print $c ?? 'a'; // a
print "\n";
print $c ?: 'a'; // Notice: Undefined variable: c in /in/apAIb on line 14
print "\n";
$b = array('a' => null);
print $b['a'] ?? 'd'; // d
print "\n";
print $b['a'] ?: 'd'; // d
print "\n";
print $b['c'] ?? 'e'; // e
print "\n";
print $b['c'] ?: 'e'; // Notice: Undefined index: c in /in/apAIb on line 33
print "\n";
Các dòng có thông báo là những dòng mà tôi đang sử dụng toán tử tốc độ nhanh trái ngược với toán tử liên kết null. Tuy nhiên, ngay cả với thông báo, PHP sẽ trả lời tương tự.
Thực thi mã: https://3v4l.org/McavC
Tất nhiên, điều này luôn luôn giả định là đối số đầu tiên null
. Khi nó không còn là null nữa, thì cuối cùng bạn sẽ có sự khác biệt ở chỗ ??
toán tử sẽ luôn trả về đối số đầu tiên trong khi tốc ?:
ký sẽ chỉ khi đối số đầu tiên là trung thực và điều đó phụ thuộc vào cách PHP sẽ phân loại mọi thứ thành boolean .
Vì thế:
$a = false ?? 'f'; // false
$b = false ?: 'g'; // 'g'
sau đó sẽ có $a
bằng false
và $b
bằng 'g'
.
$b = []; var_dump($b['a']['b']['c'] ?? 'default');
hoặc với các đối tượng$b = new Foo; var_dump($b->a()->b()->c() ?? 'default');
$a = [];
. Xem: 3v4l.org/iCCa0
Chạy bên dưới trên chế độ tương tác php ( php -a
trên thiết bị đầu cuối). Nhận xét trên mỗi dòng cho thấy kết quả.
var_dump (false ?? 'value2'); # bool(false)
var_dump (true ?? 'value2'); # bool(true)
var_dump (null ?? 'value2'); # string(6) "value2"
var_dump ('' ?? 'value2'); # string(0) ""
var_dump (0 ?? 'value2'); # int(0)
var_dump (false ?: 'value2'); # string(6) "value2"
var_dump (true ?: 'value2'); # bool(true)
var_dump (null ?: 'value2'); # string(6) "value2"
var_dump ('' ?: 'value2'); # string(6) "value2"
var_dump (0 ?: 'value2'); # string(6) "value2"
??
:??
giống như một "cánh cổng" chỉ cho phép NULL đi qua .NULL
. ??
là giống như( !isset() || is_null() )
?:
?:
giống như một cánh cổng cho phép anything falsy
đi qua - bao gồmNULL
0
, empty string
, NULL
, false
, !isset()
, empty()
.. bất cứ thứ gì có mùi falsyecho ($x ? $x : false)
?:
sẽ đưa PHP NOTICE
vào các biến không xác định ( unset
hoặc !isset()
)??
và ?:
..?:
khi
empty($x)
kiểm tra!empty($x) ? $x : $y
có thể được rút ngắn để$x ?: $y
if(!$x) { fn($x); } else { fn($y); }
có thể rút ngắn thành fn(($x ?: $y))
??
khi
!isset() || is_null()
kiểm tra$object = $object ?? new objClassName();
Toán tử Ternary có thể được xếp chồng lên nhau ...
echo 0 ?: 1 ?: 2 ?: 3; //1
echo 1 ?: 0 ?: 3 ?: 2; //1
echo 2 ?: 1 ?: 0 ?: 3; //2
echo 3 ?: 2 ?: 1 ?: 0; //3
echo 0 ?: 1 ?: 2 ?: 3; //1
echo 0 ?: 0 ?: 2 ?: 3; //2
echo 0 ?: 0 ?: 0 ?: 3; //3
Về cơ bản, đây là một chuỗi:
if( truthy ) {}
else if(truthy ) {}
else if(truthy ) {}
..
else {}
Toán tử than Null có thể được xếp chồng lên nhau ...
$v = $x ?? $y ?? $z;
Đây là một chuỗi:
if(!isset($x) || is_null($x) ) {}
else if(!isset($y) || is_null($y) ) {}
else {}
Sử dụng xếp chồng, tôi có thể rút ngắn điều này:
if(!isset($_GET['name'])){
if($user_name){
$name = $user_name;
}else {
$name = 'anonymous';
}
} else {
$name = $_GET['name'];
}
Về điều này:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
Thật tuyệt phải không? :-)
Nếu bạn sử dụng toán tử ternary phím tắt như thế này, nó sẽ gây ra thông báo nếu $_GET['username']
không được đặt:
$val = $_GET['username'] ?: 'default';
Vì vậy, thay vì bạn phải làm một cái gì đó như thế này:
$val = isset($_GET['username']) ? $_GET['username'] : 'default';
Các nhà khai thác vô coalescing tương đương với tuyên bố trên, và sẽ trở lại 'mặc định' nếu $_GET['username']
không được thiết lập hoặc là null
:
$val = $_GET['username'] ?? 'default';
Lưu ý rằng nó không kiểm tra tính trung thực . Nó chỉ kiểm tra nếu nó được đặt và không null.
Bạn cũng có thể làm điều này và giá trị được xác định (đặt và không null
) đầu tiên sẽ được trả về:
$val = $input1 ?? $input2 ?? $input3 ?? 'default';
Bây giờ đó là một toán tử liên kết thích hợp.
Sự khác biệt chính là
Ternary hành biểu hiện expr1 ?: expr3
lợi nhuận expr1
nếu expr1
đánh giá lại để
TRUE
nhưng mặt khác Null coalescing hành biểu hiện (expr1) ?? (expr2)
đánh giá lại để expr1
nếu expr1
là không NULL
Toán tử Ternary expr1 ?: expr3
phát ra một thông báo nếu giá trị bên trái (expr1)
không tồn tại nhưng mặt khác, Toán tử hợp nhất Null (expr1) ?? (expr2)
Đặc biệt, không phát ra thông báo nếu giá trị bên trái (expr1)
không tồn tại, giống như isset()
.
TernaryOperator là liên kết trái
((true ? 'true' : false) ? 't' : 'f');
Toán tử hợp nhất Null là liên kết đúng
($a ?? ($b ?? $c));
Bây giờ hãy giải thích sự khác biệt giữa bằng ví dụ:
Toán tử Ternary (?:)
$x='';
$value=($x)?:'default';
var_dump($value);
// The above is identical to this if/else statement
if($x){
$value=$x;
}
else{
$value='default';
}
var_dump($value);
Toán tử hợp nhất Null (??)
$value=($x)??'default';
var_dump($value);
// The above is identical to this if/else statement
if(isset($x)){
$value=$x;
}
else{
$value='default';
}
var_dump($value);
Dưới đây là bảng giải thích sự khác biệt và tương đồng giữa '??'
và?:
Lưu ý đặc biệt: toán tử hợp nhất null và toán tử ternary là một biểu thức và nó không đánh giá một biến, nhưng là kết quả của một biểu thức. Điều này rất quan trọng để biết nếu bạn muốn trả về một biến bằng cách tham chiếu. Tuyên bố trả về $ foo ?? $ thanh; và trả lại $ var == 42? $ a: $ b; do đó, trong một hàm trả về tham chiếu sẽ không hoạt động và cảnh báo được đưa ra.
Cả hai đều hành xử khác nhau khi xử lý dữ liệu động.
Nếu biến trống (''), phép kết hợp null sẽ coi biến là đúng nhưng toán tử ternary viết tắt sẽ không. Và đó là điều cần phải có trong tâm trí.
$a = NULL;
$c = '';
print $a ?? '1b';
print "\n";
print $a ?: '2b';
print "\n";
print $c ?? '1d';
print "\n";
print $c ?: '2d';
print "\n";
print $e ?? '1f';
print "\n";
print $e ?: '2f';
Và đầu ra:
1b
2b
2d
1f
Notice: Undefined variable: e in /in/ZBAa1 on line 21
2f
Liên kết: https://3v4l.org/ZBAa1
It returns its first operand if it exists and is not NULL; otherwise it returns its second operand
.
Cả hai đều là tốc ký cho các biểu thức dài hơn.
?:
là chữ viết tắt $a ? $a : $b
. Biểu thức này sẽ ước tính thành $ a nếu $ a ước lượng thành TRUE .
??
là chữ viết tắt isset($a) ? $a : $b
. Biểu thức này sẽ ước tính thành $ a nếu $ a được đặt và không null.
Các trường hợp sử dụng của chúng trùng nhau khi $ a không xác định hoặc null. Khi $ a không được xác định ??
sẽ không tạo ra E_NOTICE, nhưng kết quả là như nhau. Khi $ a là null thì kết quả là như nhau.
Dành cho người mới bắt đầu:
Toán tử hợp nhất Null (??)
Mọi thứ đều đúng ngoại trừ null
các giá trị và không xác định (thuộc tính biến / chỉ mục / mảng)
Ví dụ:
$array = [];
$object = new stdClass();
var_export (false ?? 'second'); # false
var_export (true ?? 'second'); # true
var_export (null ?? 'second'); # 'second'
var_export ('' ?? 'second'); # ""
var_export ('some text' ?? 'second'); # "some text"
var_export (0 ?? 'second'); # 0
var_export ($undefinedVarible ?? 'second'); # "second"
var_export ($array['undefined_index'] ?? 'second'); # "second"
var_export ($object->undefinedAttribute ?? 'second'); # "second"
về cơ bản, hãy kiểm tra biến (chỉ số mảng, thuộc tính đối tượng .. vv) có tồn tại hay không null
. tương tự như isset
chức năng
Viết tắt của toán tử ternary (? :)
mỗi điều sai ( false
, null
, 0
, chuỗi rỗng) đều được đến như sai, nhưng nếu đó là không xác định nó cũng đi kèm như sai nhưng Notice
sẽ ném
Ví dụ
$array = [];
$object = new stdClass();
var_export (false ?: 'second'); # "second"
var_export (true ?: 'second'); # true
var_export (null ?: 'second'); # "second"
var_export ('' ?: 'second'); # "second"
var_export ('some text' ?? 'second'); # "some text"
var_export (0 ?: 'second'); # "second"
var_export ($undefinedVarible ?: 'second'); # "second" Notice: Undefined variable: ..
var_export ($array['undefined_index'] ?: 'second'); # "second" Notice: Undefined index: ..
var_export ($object->undefinedAttribute ?: 'second'); # "Notice: Undefined index: ..
Hi vọng điêu nay co ich
Cuộn xuống liên kết này và xem phần này, nó cung cấp cho bạn một ví dụ so sánh như được thấy dưới đây:
<?php
/** Fetches the value of $_GET['user'] and returns 'nobody' if it does not exist. **/
$username = $_GET['user'] ?? 'nobody';
/** This is equivalent to: **/
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
/** Coalescing can be chained: this will return the first defined value out of $_GET['user'], $_POST['user'], and 'nobody'. **/
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
?>
Tuy nhiên, không nên xâu chuỗi các toán tử vì nó làm cho việc hiểu mã khó hơn khi đọc nó sau này.
Toán tử hợp nhất null (??) đã được thêm vào dưới dạng đường cú pháp cho trường hợp phổ biến là cần sử dụng một ternary kết hợp với isset (). Nó trả về toán hạng đầu tiên của nó nếu nó tồn tại và không phải là NULL; nếu không, nó trả về toán hạng thứ hai của nó.
Về cơ bản, sử dụng toán tử liên kết sẽ làm cho nó tự động kiểm tra null không giống như toán tử ternary.
a || b || c
mô hình phổ biến trong JS, ngoại trừ PHP có thể được sử dụng cho booleans ( false || 2
trong JS là 2; false ?? 2
trong PHP là sai)
Các câu trả lời khác đi sâu và đưa ra lời giải thích tuyệt vời. Đối với những người tìm kiếm câu trả lời nhanh chóng,
$a ?: 'fallback'
Là $a ? $a : 'fallback'
trong khi
$a ?? 'fallback'
Là $a = isset($a) ? $a : 'fallback'
Sự khác biệt chính sẽ là khi toán tử bên trái là:
0
, ''
, false
, []
, ...)$a =
sự mở rộng ở trên ??
. $a ?? 'fallback'
không đặt hoặc thay đổi giá trị của $ a. (Nó chỉ trả về một giá trị).
Dường như có những ưu và nhược điểm để sử dụng một trong hai ??
hoặc ?:
. Việc sử dụng chuyên nghiệp ?:
là nó đánh giá sai và null và "" giống nhau. Con lừa là nó báo cáo E_NOTICE nếu đối số trước là null. Với ??
pro là không có E_NOTICE, nhưng con lừa là nó không đánh giá sai và null giống nhau. Theo kinh nghiệm của tôi, tôi đã thấy mọi người bắt đầu sử dụng null và false thay thế cho nhau nhưng cuối cùng họ dùng đến việc sửa đổi mã của họ để phù hợp với việc sử dụng null hoặc false, nhưng không phải cả hai. Một cách khác là tạo ra một điều kiện ternary phức tạp hơn : (isset($something) or !$something) ? $something : $something_else
.
Sau đây là một ví dụ về sự khác biệt của việc sử dụng ??
toán tử bằng cả null và false:
$false = null;
$var = $false ?? "true";
echo $var . "---<br>";//returns: true---
$false = false;
$var = $false ?? "true";
echo $var . "---<br>"; //returns: ---
Tuy nhiên, bằng cách xây dựng toán tử ternary, chúng ta có thể tạo ra một chuỗi "" sai hoặc rỗng "hoạt động như thể nó là null mà không cần ném e_notice:
$false = null;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---
$false = false;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---
$false = "";
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---
$false = true;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: 1---
Cá nhân, tôi nghĩ sẽ thật tuyệt nếu một phiên bản PHP trong tương lai có một toán tử mới khác: :?
thay thế cú pháp trên. tức là:
// $var = $false :? "true";
Cú pháp đó sẽ đánh giá null, false và "" bằng nhau và không ném E_NOTICE ...
?? null ?:
điều này là khá tuyệt vời, cảm ơn bạn. anh chàng thông minh.
class a
{
public $a = 'aaa';
}
$a = new a();
echo $a->a; // Writes 'aaa'
echo $a->b; // Notice: Undefined property: a::$b
echo $a->a ?? '$a->a does not exists'; // Writes 'aaa'
// Does not throw an error although $a->b does not exist.
echo $a->b ?? '$a->b does not exist.'; // Writes $a->b does not exist.
// Does not throw an error although $a->b and also $a->b->c does not exist.
echo $a->b->c ?? '$a->b->c does not exist.'; // Writes $a->b->c does not exist.
Null Coalescing operator
thực hiện chỉ hai nhiệm vụ: nó kiểm tra whether the variable is set
và whether it is null
. Hãy xem ví dụ sau:
<?php
# case 1:
$greeting = 'Hola';
echo $greeting ?? 'Hi There'; # outputs: 'Hola'
# case 2:
$greeting = null;
echo $greeting ?? 'Hi There'; # outputs: 'Hi There'
# case 3:
unset($greeting);
echo $greeting ?? 'Hi There'; # outputs: 'Hi There'
Ví dụ mã ở trên nói rằng Null Coalescing operator
xử lý một biến không tồn tại và một biến được đặt NULL
theo cùng một cách.
Null Coalescing operator
là một cải tiến trên ternary operator
. Hãy xem đoạn mã sau đây so sánh hai đoạn mã sau:
<?php /* example: checking for the $_POST field that goes by the name of 'fullname'*/
# in ternary operator
echo "Welcome ", (isset($_POST['fullname']) && !is_null($_POST['fullname']) ? $_POST['fullname'] : 'Mr. Whosoever.'); # outputs: Welcome Mr. Whosoever.
# in null coalecing operator
echo "Welcome ", ($_POST['fullname'] ?? 'Mr. Whosoever.'); # outputs: Welcome Mr. Whosoever.
Vì vậy, sự khác biệt giữa hai là Null Coalescing operator
toán tử được thiết kế để xử lý các biến không xác định tốt hơn so vớiternary operator
. Trong khi đó, ternary operator
là một tốc ký cho if-else
.
Null Coalescing operator
không có nghĩa là để thay thế ternary operator
, nhưng trong một số trường hợp sử dụng như trong ví dụ trên, nó cho phép bạn viết mã sạch với ít rắc rối hơn.
Tín dụng: http://dwellupper.io/post/6/php7-null-coalescing-operator-usage-and-examples
isset($_POST['fullname'])
đã kiểm tra các NULL
giá trị - vì vậy && !is_null($_POST['fullname'])
trong ví dụ đầu tiên là không cần thiết
Khi sử dụng các siêu lớp như $ _GET hoặc $ _REQUEST, bạn nên biết rằng chúng có thể là một chuỗi rỗng. Trong trường hợp cụ thể này, ví dụ này
$username = $_GET['user'] ?? 'nobody';
sẽ thất bại vì giá trị của tên người dùng $ bây giờ là một chuỗi rỗng.
Vì vậy, khi sử dụng $ _GET hoặc thậm chí $ _REQUEST, bạn nên sử dụng toán tử ternary thay vì như thế này:
$username = (!empty($_GET['user'])?$_GET['user']:'nobody';
Bây giờ giá trị của tên người dùng $ là 'không ai' như mong đợi.