PHP 8 มีอะไรใหม่ (คุณสมบัติใหม่, การเปลี่ยนแปลง, ความปลอดภัยและคอมไพเลอร์ JIT)
PHP 8 เป็นการอัพเดทครั้งใหญ่ของภาษา PHP ประกอบด้วยคุณสมบัติใหม่และการเพิ่มประสิทธิภาพมากมาย โดยได้เพิ่มความสามารถใหม่ๆ และ Syntax ของภาษาให้ทันสมัยมากยิ่งขึ้น เราจะมาบอกเล่าเกี่ยวกับฟีเจอร์ใหม่ของ PHP 8 ที่น่าสนใจ โดย PHP 8 ให้ความปลอดภัยที่มากขึ้นและการจัดการข้อผิดพลาดที่ดีขึ้น รายละเอียดมีอะไรใหม่บ้างมาดูกันเลย
Named arguments
Named arguments อนุญาตให้ส่งผ่านอาร์กิวเมนต์ไปยังฟังก์ชันตามชื่อพารามิเตอร์ แทนที่จะเป็นตำแหน่งพารามิเตอร์ ซึ่งหมายความว่าอาร์กิวเมนต์นั้นไม่ต้องเรียงตามลำดับก็ได้ ตัวอย่างด้านล่างจะช่วยให้ต่อยอดแนวคิดของคุณ
// การใช้อาร์กิวเมนต์ตามตำแหน่ง
array_fill(0, 100, 50);
// การใช้อาร์กิวเมนต์ที่มีชื่อ (โดยสามารถสลับหรือข้ามตำแหน่งได้)
array_fill(start_index: 0, num: 100, value: 50);
Union types
Union types ยอมรับค่าประเภทต่างๆ หลายประเภท แทนที่จะเป็นประเภทเดียว PHP รองรับตัวแปรสองประเภทแล้ว มีการระบุประเภทให้กับตัวแปรโดยใช้ Type1|Type2|null และสามารถใช้ได้ในทุกตำแหน่งที่ยอมรับประเภทในปัจจุบัน
class Number {
private int|float $number;
public function setNumber(int|float $number): void {
$this->number = $number;
}
public function getNumber(): int|float {
return $this->number;
}
}
Attributes
ทำให้เราสามารถเพิ่มข้อมูล meta ได้โดยไม่ต้องใช้ comment หรือ docblocks แนวคิดที่คล้ายกันนี้มีอยู่ในภาษาอื่นๆ ที่ชื่อว่า Annotations ใน Java, Attributes ใน C#, C++, Rust, Hack และ Decorators ใน Python และ Javascript แอตทริบิวต์เป็นข้อความที่มีรูปแบบพิเศษล้อมรอบด้วย "<<" และ ">>" แอตทริบิวต์อาจนำไปใช้กับฟังก์ชัน คลาส ค่าคงที่ของคลาส คุณสมบัติของคลาส เมธอดคลาส และพารามิเตอร์ฟังก์ชัน/เมธอด ดูตัวอย่างต่อไปนี้
<<ExampleAttribute>> class Foo { <<ExampleAttribute>> public const FOO = 'foo'; <<ExampleAttribute>> public $x; <<ExampleAttribute>> public function foo(<<ExampleAttribute>> $bar) { } } $object = new <<ExampleAttribute>> class () { }; <<ExampleAttribute>> function f1() { } $f2 = <<ExampleAttribute>> function () { }; $f3 = <<ExampleAttribute>> fn () => 1;
Constructor Property
Constructor Property ทำให้การประกาศคุณสมบัติง่าย สั้นลง และซ้ำซ้อนน้อยลง เดิมทีเรามีการส่งค่าตัวแปรไปใน Constructor แล้วเราต้องประกาศ Property ขึ้นมารองรับตัวแปรจาก Constructor
class Point {
public float $x;
public float $y;
public float $z;
public function __construct(
float $x = 0.0,
float $y = 0.0,
float $z = 0.0,
) {
$this->x = $x;
$this->y = $y;
$this->z = $z;
}
}
PHP 8 เราสามารถเขียนแบบนี้ได้เลย
class Point {
public function __construct(
public float $x = 0.0,
public float $y = 0.0,
public float $z = 0.0,
) {}
}
Match expression
การจับคู่ใหม่คล้ายกับ switch แต่ดีกว่านั้น หากเงื่อนไขหลายรายการสามารถคั่นด้วยเครื่องหมายจุลภาค (,) เพื่อเปรียบเทียบค่า คำสั่ง switch เปรียบเทียบ (==) ค่าที่กำหนดกับค่าตัวพิมพ์อย่างหลวมๆ แต่นิพจน์การจับคู่ใช้การเปรียบเทียบอย่างเข้มงวด (===) แทน
switch ($x) {
case 0:
$result = 'Car';
break;
case 1:
$result = 'Bus';
break;
case 2:
$result = 'Bike';
break;
}
echo $result;
// PHP 8 ทำแบบนี้ได้
echo match ($x) {
0 => 'Car',
1 => 'Bus',
2 => 'Bike',
};
echo match ($x) {
1, 2 => 'Same for 1 and 2',
3, 4 => 'Same for 3 and 4',
};
nullsafe operator
ในเวอร์ชันก่อนหน้าของ PHP การตรวจสอบค่า null นำไปสู่การซ้อนและการทำซ้ำที่ลึกขึ้นเรื่อยๆ PHP 8 แนะนำตัวดำเนินการ nullsafe ใหม่ ตามตัวอย่าง
// แบบเดิม
$country = null;
if ($session !== null) {
$user = $session->user;
if ($user !== null) {
$address = $user->getAddress();
if ($address !== null) {
$country = $address->country;
}
}
}
// แบบใหม่ใน php 8
$country = $session?->user?->getAddress()?->country;
การเปรียบเทียบประเภทตัวอักษรกับตัวเลข
การเปรียบเทียบระหว่างสตริงและตัวเลขโดยใช้ == และตัวดำเนินการเปรียบเทียบที่ไม่เข้มงวดอื่นๆ ในปัจจุบันทำงานโดยการส่งสตริงเป็นตัวเลข แล้วทำการเปรียบเทียบจำนวนเต็มหรือทศนิยม ซึ่งส่งผลให้เกิดผลลัพธ์การเปรียบเทียบที่น่าประหลาดใจมากมาย เช่น 0 == "foobar" คืนค่าจริง แต่ใน php 8 คืนค่าเท็จ
PHP 8 New Functions
str_contains
str_contains ตรวจสอบว่าสตริงมีอยู่ในสตริงอื่นหรือไม่ และส่งคืนค่าบูลีนจริงหากพบสตริงนั้น และส่งคืนค่าเท็จหากไม่พบสตริงนั้น ใน PHP เวอร์ชันก่อนหน้า มีการใช้ strpos และ strstr สำหรับสิ่งนี้ซึ่งมีข้อเสียเล็กน้อย วิธีการทำงานของฟังก์ชัน str_contains ตามตัวอย่างด้านล่าง
str_contains("abc", "a"); // true
str_contains("abc", "d"); // false
// หากเป็นสตริงว่าง
str_contains("abc", ""); // true
str_contains("", ""); // true
str_starts_with() และ str_ends_with()
str_starts_with และ str_ends_with เป็นฟังก์ชันใหม่ของ PHP ที่คล้ายกับ str_contains แต่ str_starts_with ตรวจสอบว่าสตริงเริ่มต้นด้วยสตริงอื่นหรือไม่ และส่งกลับค่าบูลีน (จริง/เท็จ) และ str_ends_with ตรวจสอบว่าสตริงลงท้ายด้วยสตริงอื่นหรือไม่ และส่งกลับค่าบูลีน (จริง/เท็จ) ว่าเป็นเช่นนั้นหรือไม่
str_starts_with (string $haystack , string $needle) : bool
str_ends_with (string $haystack , string $needle) : bool
get_debug_type
ฟังก์ชันใหม่ get_debug_type จะส่งคืนตัวแปรประเภทที่กำหนด ฟังก์ชันนี้จะแตกต่างจาก gettype ซึ่งจะส่งคืนชื่อประเภทดั้งเดิม เช่น "int" แทนที่จะเป็น "integer" ตารางต่อไปนี้แสดงสิ่งที่ get_debug_type() ส่งคืนสำหรับค่าต่างๆ และสิ่งที่ gettype() ส่งคืนแตกต่างสำหรับค่าเดียวกัน
| Value | get_debug_type() | gettype() |
| 0 | int | integer |
| 0.1 | float | double |
| true | bool | boolean |
| false | bool | boolean |
| “hello” | string | |
| [] | array | |
| null | null | NULL |
| A class with name “Foo\Bar” | Foo\Bar | object |
| An anonymous class | class@anonymous | object |
| A resource | resource (xxx) | resource |
| A closed resource | resource (closed) |
ตัวอย่างการใช้งานแบบเดิมกับแบบใหม่
$bar = $arr['key'];
if (!($bar instanceof Foo)) {
// this shows the most simple of patterns, to get the real type an assoc array
// must be present to convert long-form "integer" into int etc.
throw new TypeError('Expected ' . Foo::class . ' got ' . (is_object($bar) ? get_class($bar) : gettype($bar)));
}
// ใน PHP 8.0 เราสามารถใช้ฟังก์ชัน get_debug_type สำหรับกรณีการใช้งานข้างต้นดังนี้
if (!($bar instanceof Foo)) {
throw new TypeError('Expected ' . Foo::class . ' got ' . get_debug_type($bar));
}
PHP JIT Compiler
PHP 8 มาพร้อมกับฟีเจอร์ใหม่ JIT (Just-In-Time) Compilation คือคอมไพล์ในขณะรันไทม์และรันโค้ดโดยตรงในเครื่องเสมือน ในทางกลับกัน การเขียนโปรแกรมด้วยการรวบรวม Ahead-of-Time (AOT) จำเป็นต้องรวบรวมโค้ดก่อนที่จะรัน การคอมไพล์ JIT เป็นรูปแบบไฮบริดการคอมไพล์ล่วงหน้า ซึ่งโค้ดบางส่วนหรือทั้งหมดจะถูกคอมไพล์ โดยมักจะอยู่ที่รันไทม์ โดยไม่จำเป็นต้องให้นักพัฒนาคอมไพล์ด้วยตนเอง
PHP JIT ถูกนำมาใช้เป็นส่วนที่เกือบจะเป็นอิสระจาก OPcache อาจเปิด/ปิดในเวลาคอมไพล์ PHP และขณะรันไทม์ เมื่อเปิดใช้งาน โค้ดของไฟล์ PHP จะถูกจัดเก็บไว้ในขอบเขตเพิ่มเติมของหน่วยความจำที่ใช้ร่วมกันของ OPcache และ op_array->opcodes[].handler(s) จะเก็บตัวชี้ไปยังจุดเข้าใช้งานของโค้ด JIT-ed
สรุป
เราได้กล่าวถึงคุณลักษณะใหม่ การเพิ่มประสิทธิภาพ ฟังก์ชันใหม่ คอมไพเลอร์ Just In Time ฯลฯ หวังว่าบล็อกนี้จะช่วยให้คุณเข้าใจ PHP 8 ได้ดี