บทความ

Array unpacking ด้วย string key ใน PHP 8.1 ใช้แทน array_merge ได้ยังไง

ตั้งแต่ PHP 8.1 เรากระจาย array ที่มี string key ด้วย ... ได้แล้ว ได้ผลเหมือน array_merge() คือ key ซ้ำตัวหลังชนะ ต่างจากเครื่องหมาย + ที่เก็บตัวหน้าไว้

เผยแพร่
อัปเดต
— เพิ่มตัวอย่างเทียบกับเครื่องหมาย + และกรณี key เป็นตัวเลข
เวลาอ่าน
1 นาที
แท็ก
#PHP

PHP 7.4 ให้เราใช้ ... กระจาย array ลงไปใน array อีกตัวได้ คล้าย spread syntax ใน JavaScript แต่ใช้ได้เฉพาะ array ที่ key เป็นตัวเลข พอถึง PHP 8.1 ก็ใช้กับ array ที่มี string key ได้แล้ว โค้ดในโพสต์นี้รันบน PHP 8.4 ได้เหมือนกันทุกตัว

PHP 7.4 กระจายได้เฉพาะ key ที่เป็นตัวเลข

[1, ...[2, 3, 4], 5];
// [1, 2, 3, 4, 5]

ถ้า array มี string key PHP 7.4 กับ 8.0 จะ error ว่า Cannot unpack array with string keys เราเลยต้องรวม array ด้วย array_merge() แบบนี้

$defaults = ['a' => 1, 'b' => 2];
$input = ['a' => 3];

$actual = array_merge($defaults, $input);
// ['a' => 3, 'b' => 2]

PHP 8.1 กระจาย string key ได้แล้ว

$actual = [...$defaults, ...$input];
// ['a' => 3, 'b' => 2]

// เขียน key เองปนกับตัวที่กระจายก็ได้
$actual = ['a' => 1, 'b' => 2, ...$input];
// ['a' => 3, 'b' => 2]

// แทรกไว้กลาง array ก็ได้
['a' => 1, ...['b' => 2, 'c' => 3], 'd' => 4];
// ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4]

ผลลัพธ์ออกมาเหมือน array_merge() ทุกอย่าง แต่อ่านง่ายกว่า โดยเฉพาะตอนเอา option ที่ผู้ใช้ส่งมาทับค่าเริ่มต้น RFC ของ Nikita Popov เลือกให้ทำงานแบบ array_merge() ตั้งแต่แรก ถ้า string key ซ้ำกัน ค่าจาก array ตัวหลังชนะ

key ซ้ำกัน ... เก็บตัวหลัง แต่ + เก็บตัวหน้า

เครื่องหมาย + ก็รวม array ได้ แต่ทำกลับกัน + เก็บค่าจาก array ตัวหน้า แล้วเติมเฉพาะ key ที่ตัวหน้ายังไม่มี

$defaults = ['a' => 1, 'b' => 2];
$input = ['a' => 3];

[...$defaults, ...$input]; // ['a' => 3, 'b' => 2]
$defaults + $input;        // ['a' => 1, 'b' => 2]
$input + $defaults;        // ['a' => 3, 'b' => 2]

ถ้าจะใช้ + เติมค่าเริ่มต้น ต้องเอา $input ขึ้นก่อน สลับลำดับเมื่อไหร่ ค่าที่ผู้ใช้ส่งมาหายเงียบ ๆ

key เป็น id ให้ใช้ + เพราะ ... เรียงเลขใหม่

key ที่เป็นตัวเลข ... กับ array_merge() จะเรียงเลขใหม่ตั้งแต่ 0 ถ้า key คือ id เช่น array ที่ได้จาก pluck('name', 'id') ใน Laravel id จะหายหมด

$staff = [10 => 'สมชาย', 12 => 'สุดา'];
$managers = [15 => 'อนันต์'];

[...$staff, ...$managers];
// [0 => 'สมชาย', 1 => 'สุดา', 2 => 'อนันต์']

$staff + $managers;
// [10 => 'สมชาย', 12 => 'สุดา', 15 => 'อนันต์']

แบบนี้ใช้ + แทน ได้ id ครบตามเดิม

อ้างอิง

อ่านต่อ

ล่าสุด

ดูทั้งหมด →