บางคนสามารถอธิบายความแตกต่างระหว่างตัวดำเนินการแบบไตรภาค shorthand ( ?:
) และตัวดำเนินการรวมค่า null ( ??
) ใน PHP ได้หรือไม่?
เมื่อไหร่ที่พวกเขาประพฤติแตกต่างกันและเมื่อในลักษณะเดียวกัน (ถ้าเป็นเช่นนั้น)
$a ?: $b
VS.
$a ?? $b
บางคนสามารถอธิบายความแตกต่างระหว่างตัวดำเนินการแบบไตรภาค shorthand ( ?:
) และตัวดำเนินการรวมค่า null ( ??
) ใน PHP ได้หรือไม่?
เมื่อไหร่ที่พวกเขาประพฤติแตกต่างกันและเมื่อในลักษณะเดียวกัน (ถ้าเป็นเช่นนั้น)
$a ?: $b
VS.
$a ?? $b
คำตอบ:
เมื่ออาร์กิวเมนต์แรกของคุณเป็นโมฆะมันจะเหมือนกันโดยทั่วไปยกเว้นว่าการรวมกันเป็นโมฆะจะไม่ส่งออกE_NOTICE
เมื่อคุณมีตัวแปรที่ไม่ได้กำหนด PHP 7.0 เอกสารการย้ายถิ่นได้นี้จะพูดว่า:
ตัวดำเนินการรวมศูนย์ว่าง (??) ได้รับการเพิ่มเป็นน้ำตาลเชิงประโยคสำหรับกรณีทั่วไปที่จำเป็นต้องใช้ ternary ร่วมกับ isset () มันจะส่งกลับตัวถูกดำเนินการแรกถ้ามันมีอยู่และไม่เป็นโมฆะ; มิฉะนั้นจะส่งคืนตัวถูกดำเนินการที่สอง
นี่คือตัวอย่างรหัสที่จะสาธิต:
<?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";
เส้นที่มีการแจ้งให้ทราบนั้นเป็นสิ่งที่ฉันใช้ตัวดำเนินการแบบย่อและสั้นซึ่งต่างจากตัวดำเนินการรวมตัวที่ว่าง อย่างไรก็ตามแม้จะมีการแจ้งเตือน PHP จะให้การตอบกลับแบบเดียวกัน
เรียกใช้งานโค้ด: https://3v4l.org/McavC
null
ของหลักสูตรนี้อยู่เสมอสมมติว่าอาร์กิวเมนต์แรกคือ เมื่อมันไม่ null อีกต่อไปแล้วคุณจะจบลงด้วยความแตกต่างในการที่??
ผู้ประกอบการมักจะกลับอาร์กิวเมนต์แรกในขณะที่?:
ชวเลขจะเฉพาะในกรณีที่อาร์กิวเมนต์แรกเป็น truthy และที่อาศัยวิธีPHP จะพิมพ์หล่อสิ่งที่บูล
ดังนั้น:
$a = false ?? 'f'; // false
$b = false ?: 'g'; // 'g'
ก็จะมี$a
เท่ากับfalse
และเท่ากับ$b
'g'
$b = []; var_dump($b['a']['b']['c'] ?? 'default');
หรือกับวัตถุ$b = new Foo; var_dump($b->a()->b()->c() ?? 'default');
$a = [];
โปรดทราบว่าการทำงานยังแตกต่างกันด้วย ดู: 3v4l.org/iCCa0
เรียกใช้ด้านล่างในโหมดโต้ตอบ php ( php -a
บนเทอร์มินัล) ความคิดเห็นในแต่ละบรรทัดแสดงผลลัพธ์
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"
??
:??
เป็นเหมือน "ประตู" ที่อนุญาตให้ NULL ผ่านเท่านั้นNULL
??
นี้เหมือนกับ( !isset() || is_null() )
?:
?:
เปรียบเหมือนประตูที่ปล่อยanything falsy
ผ่าน - รวมทั้งNULL
0
, empty string
, NULL
, false
, !isset()
, empty()
.. อะไรที่มีกลิ่น falsyecho ($x ? $x : false)
?:
จะโยนตัวแปรที่PHP NOTICE
ไม่ได้กำหนด ( unset
หรือ!isset()
)??
และ?:
..?:
เมื่อ
empty($x)
ตรวจสอบ!empty($x) ? $x : $y
สามารถสั้นลงไป$x ?: $y
if(!$x) { fn($x); } else { fn($y); }
สามารถตัดให้สั้นลง fn(($x ?: $y))
??
เมื่อ
!isset() || is_null()
ตรวจสอบ$object = $object ?? new objClassName();
ผู้ประกอบการ Ternary สามารถซ้อน ...
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
แหล่งที่มาและเครดิตสำหรับรหัสนี้
นี่เป็นลำดับของ:
if( truthy ) {}
else if(truthy ) {}
else if(truthy ) {}
..
else {}
ตัวดำเนินการ Null Coalese สามารถซ้อน ...
$v = $x ?? $y ?? $z;
นี่คือลำดับของ:
if(!isset($x) || is_null($x) ) {}
else if(!isset($y) || is_null($y) ) {}
else {}
ใช้การซ้อนฉันสามารถย่อ:
if(!isset($_GET['name'])){
if($user_name){
$name = $user_name;
}else {
$name = 'anonymous';
}
} else {
$name = $_GET['name'];
}
สำหรับสิ่งนี้:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
เจ๋งใช่มั้ย :-)
หากคุณใช้ผู้ประกอบการทางลัดแบบนี้มันจะทำให้เกิดการแจ้งเตือนหาก$_GET['username']
ไม่ได้ตั้ง:
$val = $_GET['username'] ?: 'default';
ดังนั้นคุณต้องทำสิ่งนี้แทน:
$val = isset($_GET['username']) ? $_GET['username'] : 'default';
ตัวดำเนินการรวมศูนย์ว่างเทียบเท่ากับคำสั่งด้านบนและจะส่งคืน 'ค่าเริ่มต้น' หาก$_GET['username']
ไม่ได้ตั้งค่าหรือเป็นnull
:
$val = $_GET['username'] ?? 'default';
โปรดทราบว่ามันไม่ได้ตรวจสอบความจริง มันตรวจสอบเฉพาะในกรณีที่มีการตั้งค่าและไม่เป็นโมฆะ
คุณสามารถทำเช่นนี้ได้และจะส่งคืนค่าที่กำหนดไว้ ( แรกและไม่null
):
$val = $input1 ?? $input2 ?? $input3 ?? 'default';
ตอนนี้เป็นตัวดำเนินการรวมที่เหมาะสม
ความแตกต่างที่สำคัญคือ
ประกอบไปด้วยผู้ประกอบการแสดงออกของ expr1 ?: expr3
ผลตอบแทนexpr1
หากexpr1
ประเมิน
TRUE
แต่ในมืออื่น ๆNull หลอมรวมผู้ประกอบการแสดงออก (expr1) ?? (expr2)
ประเมินexpr1
ถ้าexpr1
เป็นไม่ได้ NULL
ประกอบไปด้วยผู้ประกอบการ expr1 ?: expr3
ปล่อยแจ้งให้ทราบล่วงหน้าถ้าค่าด้านซ้าย(expr1)
ไม่ได้อยู่ แต่ในมืออื่น ๆNull หลอมรวมผู้ประกอบการ (expr1) ?? (expr2)
โดยเฉพาะอย่างยิ่งไม่ปล่อยแจ้งให้ทราบล่วงหน้าถ้าค่าด้านซ้ายไม่ได้อยู่เช่นเดียวกับ (expr1)
isset()
TernaryOperatorไม่มีการเชื่อมโยง
((true ? 'true' : false) ? 't' : 'f');
ผู้ประกอบการ Null Coalescingมีความสัมพันธ์ที่ถูกต้อง
($a ?? ($b ?? $c));
ตอนนี้ให้อธิบายความแตกต่างระหว่างตัวอย่าง:
ผู้ประกอบการที่สาม (?:)
$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);
Null Coalescing Operator (??)
$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);
นี่คือตารางที่อธิบายความแตกต่างและความคล้ายคลึงกันระหว่าง'??'
และ?:
หมายเหตุพิเศษ: ตัวดำเนินการรวมศูนย์โมฆะและตัวดำเนินการที่ประกอบไปด้วยสามคือนิพจน์และมันไม่ได้ประเมินกับตัวแปร แต่เป็นผลของการแสดงออก สิ่งนี้สำคัญที่ต้องทราบว่าคุณต้องการส่งคืนตัวแปรโดยการอ้างอิงหรือไม่ คำสั่งส่งคืน $ foo หรือไม่ $ บาร์; และส่งคืน $ var == 42? $ a: $ b; ในฟังก์ชั่น return-by-Reference จะไม่ทำงานและมีการออกคำเตือน
ทั้งคู่มีพฤติกรรมแตกต่างกันเมื่อพูดถึงการจัดการข้อมูลแบบไดนามิก
หากตัวแปรว่างเปล่า ('') การรวมค่า null จะถือว่าตัวแปรนั้นเป็นจริง แต่ตัวดำเนินการแบบย่อจะไม่ดำเนินการใด ๆ และนั่นคือสิ่งที่ต้องคำนึงถึง
$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';
และผลลัพธ์:
1b
2b
2d
1f
Notice: Undefined variable: e in /in/ZBAa1 on line 21
2f
ลิงก์: https://3v4l.org/ZBAa1
It returns its first operand if it exists and is not NULL; otherwise it returns its second operand
.
ทั้งคู่เป็นชวเลขเพื่อการแสดงออกที่ยาวขึ้น
?:
$a ? $a : $b
สั้นสำหรับ สำนวนนี้จะประเมินถึง $ ถ้า $ a ประเมินTRUE
??
isset($a) ? $a : $b
สั้นสำหรับ นิพจน์นี้จะประเมินเป็น $ a หากมีการตั้งค่า $ a และไม่ใช่ค่าว่าง
กรณีการใช้ของพวกเขาทับซ้อนกันเมื่อ $ a ไม่ได้กำหนดหรือเป็นโมฆะ เมื่อ $ a ไม่ได้ถูกกำหนด??
จะไม่สร้าง E_NOTICE แต่ผลลัพธ์จะเหมือนกัน เมื่อ $ a เป็นโมฆะผลลัพธ์จะเหมือนกัน
สำหรับผู้เริ่มต้น:
ตัวดำเนินการรวมศูนย์ Null (??)
ทุกอย่างเป็นจริงยกเว้นnull
ค่าและไม่ได้กำหนดไว้ (แอตทริบิวต์ตัวแปร / แถวลำดับ / วัตถุ)
อดีต:
$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"
นี้เป็นพื้นตรวจสอบตัวแปร (ดัชนีอาร์เรย์แอตทริบิวต์วัตถุ .. ฯลฯ ) null
เป็นที่มีอยู่และไม่ได้ คล้ายกับisset
ฟังก์ชั่น
ผู้ประกอบการที่สามจดชวเลข (? :)
ทุกสิ่งที่เป็นเท็จ ( false
, null
, 0
, สตริงว่าง) จะมาเป็นเท็จ แต่ถ้ามันเป็นไม่ได้กำหนดก็ยังมาเป็นเท็จ แต่Notice
จะโยน
อดีต
$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: ..
หวังว่านี่จะช่วยได้
เลื่อนลงไปที่ลิงค์นี้และดูส่วนมันจะให้ตัวอย่างเปรียบเทียบที่แสดงด้านล่าง:
<?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';
?>
อย่างไรก็ตามไม่ควรเชื่อมโยงตัวดำเนินการเนื่องจากทำให้เข้าใจรหัสได้ยากขึ้นเมื่ออ่านในภายหลัง
ตัวดำเนินการรวมศูนย์ว่าง (??) ได้รับการเพิ่มเป็นน้ำตาลเชิงประโยคสำหรับกรณีทั่วไปที่จำเป็นต้องใช้ ternary ร่วมกับ isset () มันจะส่งกลับตัวถูกดำเนินการแรกถ้ามันมีอยู่และไม่เป็นโมฆะ; มิฉะนั้นจะส่งคืนตัวถูกดำเนินการที่สอง
โดยพื้นฐานแล้วการใช้ตัวดำเนินการรวมกันจะทำให้การตรวจสอบอัตโนมัติเป็นโมฆะไม่เหมือนกับตัวดำเนินการแบบไตรภาค
a || b || c
ในรูปแบบ JS ยกเว้นของ PHP สามารถใช้สำหรับการบูลีน ( false || 2
ใน JS เป็น 2; false ?? 2
ใน PHP เป็นเท็จ)
คำตอบอื่น ๆ จะไปลึกและให้คำอธิบายที่ดี สำหรับผู้ที่มองหาคำตอบด่วน
$a ?: 'fallback'
คือ $a ? $a : 'fallback'
ในขณะที่
$a ?? 'fallback'
คือ $a = isset($a) ? $a : 'fallback'
ความแตกต่างที่สำคัญคือเมื่อตัวดำเนินการด้านซ้ายเป็น:
0
, ''
, false
, []
, ... )$a =
ไม่ได้ตั้งค่าหรือเปลี่ยนแปลงมูลค่าของ $ a (มันแค่คืนค่า) ??
$a ?? 'fallback'
มันดูเหมือนว่ามีข้อดีและข้อเสียของการใช้อย่างใดอย่างหนึ่งหรือ??
?:
โปรที่จะใช้?:
คือการประเมินค่าเท็จและค่า null และ "" เหมือนกัน คอนดิชั่นคือมันรายงาน E_NOTICE ถ้าอาร์กิวเมนต์ก่อนหน้านี้เป็นโมฆะ ด้วย??
โปรคือไม่มี E_NOTICE แต่ข้อผิดพลาดคือมันไม่ได้ประเมินค่า false และ null เหมือนกัน จากประสบการณ์ของฉันฉันเห็นผู้คนเริ่มใช้ null และ false interchangeably แต่ในที่สุดพวกเขาก็หันไปแก้ไขรหัสของพวกเขาให้สอดคล้องกับการใช้ null หรือ false แต่ไม่ใช่ทั้งคู่ ทางเลือกคือการสร้างเงื่อนไขที่ประกอบไปด้วยรายละเอียดเพิ่มเติม: (isset($something) or !$something) ? $something : $something_else
.
ต่อไปนี้เป็นตัวอย่างของความแตกต่างของการใช้??
โอเปอเรเตอร์โดยใช้ทั้ง null และ false:
$false = null;
$var = $false ?? "true";
echo $var . "---<br>";//returns: true---
$false = false;
$var = $false ?? "true";
echo $var . "---<br>"; //returns: ---
อย่างไรก็ตามการอธิบายอย่างละเอียดเกี่ยวกับผู้ประกอบการที่ประกอบไปด้วยเราสามารถทำให้สตริงที่เป็นเท็จหรือว่างเปล่าได้ "" ราวกับว่ามันเป็นโมฆะโดยไม่ต้องขว้าง 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---
โดยส่วนตัวฉันคิดว่ามันจะดีจริงๆถ้าการปรับปรุง PHP ในอนาคตมีผู้ให้บริการรายใหม่อีกราย: :?
แทนที่ไวยากรณ์ข้างต้น เช่น:
// $var = $false :? "true";
ไวยากรณ์นั้นจะประเมินค่า null, false และ "" เท่ากันและไม่ส่ง E_NOTICE ...
?? null ?:
มันเยี่ยมมากเลยขอบคุณ คนฉลาด
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
ดำเนินการเพียงสองงาน: การตรวจสอบมันและwhether the variable is set
whether it is null
ดูตัวอย่างต่อไปนี้:
<?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'
ตัวอย่างรหัสข้างต้นระบุว่าNull Coalescing operator
ปฏิบัติกับตัวแปรที่ไม่มีอยู่และตัวแปรที่ตั้งค่าNULL
เป็นแบบเดียวกัน
Null Coalescing operator
ternary operator
คือการปรับปรุงมากกว่า ดูตัวอย่างโค้ดต่อไปนี้เปรียบเทียบทั้งสอง:
<?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.
ดังนั้นความแตกต่างระหว่างทั้งสองคือการที่ผู้ประกอบการได้รับการออกแบบมาเพื่อจัดการกับตัวแปรที่ไม่ได้กำหนดดีกว่าNull Coalescing operator
ternary operator
ขณะที่เป็นชวเลขternary operator
if-else
Null Coalescing operator
ไม่ได้หมายถึงการแทนที่ternary operator
แต่ในบางกรณีการใช้งานเช่นในตัวอย่างด้านบนจะช่วยให้คุณสามารถเขียนโค้ดสะอาดได้โดยไม่ยุ่งยาก
เครดิต: http://dwellupper.io/post/6/php7-null-coalescing-operator-usage-and-examples
isset($_POST['fullname'])
ตรวจสอบNULL
ค่าแล้ว - ดังนั้น&& !is_null($_POST['fullname'])
ในตัวอย่างแรกนั้นซ้ำซ้อนอยู่แล้ว
เมื่อใช้ superglobals เช่น $ _GET หรือ $ _REQUEST คุณควรระวังว่ามันอาจเป็นสตริงว่าง ในกรณีพิเศษนี้ตัวอย่างนี้
$username = $_GET['user'] ?? 'nobody';
จะล้มเหลวเนื่องจากค่าของ $ username ตอนนี้เป็นสตริงว่าง
ดังนั้นเมื่อใช้ $ _GET หรือแม้แต่ $ _REQUEST คุณควรใช้โอเปอร์เรเตอร์แทนเนอร์แทนเช่นนี้:
$username = (!empty($_GET['user'])?$_GET['user']:'nobody';
ตอนนี้ค่าของชื่อผู้ใช้ $ คือ 'ไม่มีใคร' ตามที่คาดไว้