PHP 8 มีอะไรใหม่ (คุณสมบัติใหม่, การเปลี่ยนแปลง, ความปลอดภัยและคอมไพเลอร์ JIT)

แชร์
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 ได้ดี

31 มีนาคม 2566
เว็บไซต์นี้ใช้คุกกี้ที่จําเป็นในการใช้งาน โดยคุกกี้ที่ใช้ ไม่ได้มีการจัดเก็บข้อมูลที่สามารถระบุตัวตนของผู้ใช้แต่อย่างใด เรียนรู้เพิ่มเติม