บทความ

PHP 8.3 มีอะไรใหม่

ไล่ดูฟีเจอร์ของ PHP 8.3 ที่ได้ใช้ในโค้ดทั่วไป ตั้งแต่ typed class constants, #[\Override], json_validate() ไปจนถึงเรียก constant ด้วยชื่อในตัวแปร พร้อมตัวอย่างที่รันได้จริง

เผยแพร่
อัปเดต
— แก้ตัวอย่าง #[\Override] และเพิ่มสถานะซัพพอร์ตของ PHP 8.3
เวลาอ่าน
3 นาที
สรุปจาก
Brent Roose · stitcher.io
แท็ก
#PHP

ใส่ type ให้ class constant ได้แล้ว

ก่อน PHP 8.3 เราประกาศ const ในคลาสได้แค่ชื่อกับค่า ระบุ type ไม่ได้ ตั้งแต่ PHP 8.3 ใส่ type ไว้หน้าชื่อได้เหมือน property เรียกว่า typed class constants

class Post
{
    // ก่อน PHP 8.3 ระบุ type ไม่ได้
    const STATUS_DRAFT = 'draft';

    // PHP 8.3 ใส่ type ได้แล้ว
    const string STATUS_PUBLIC = 'public';
}

ถ้าใส่ค่าที่ไม่ตรงกับ type เช่น const string STATUS_PUBLIC = 1; PHP จะหยุดทันทีด้วย error นี้

Fatal error: Cannot use int as value for class constant Post::STATUS_PUBLIC of type string

RFC

#[\Override] เช็กให้ว่าเมธอดยัง override คลาสแม่อยู่จริง

ใส่ attribute #[\Override] บนเมธอดเพื่อบอกว่าเราตั้งใจ override เมธอดของคลาสแม่ (หรือของ interface) ถ้าวันหนึ่งคลาสแม่เปลี่ยนชื่อเมธอด เมธอดในคลาสลูกก็ไม่ได้ override อะไรแล้ว PHP จะฟ้อง error ให้เรารู้ตัว แทนที่โค้ดจะเงียบไปเฉย ๆ

abstract class BaseClass
{
    public function methodWithDefaultImplementation(): int
    {
        return 1;
    }
}

class Child extends BaseClass
{
    #[\Override]
    public function methodWithDefaultImplementation(): int
    {
        return 2; // override เมธอดของคลาสแม่
    }
}

ทีนี้ถ้าคลาสแม่เปลี่ยนชื่อเมธอดเป็นชื่ออื่น

abstract class BaseClass
{
    public function methodWithNewImplementation(): int
    {
        return 1;
    }
}

Child::methodWithDefaultImplementation() ก็ไม่ได้ override เมธอดไหนแล้ว PHP เห็น #[\Override] จึงหยุดด้วย error นี้

Fatal error: Child::methodWithDefaultImplementation() has #[\Override] attribute, but no matching parent method exists

RFC

Index ติดลบใน array นับต่อจากตัวล่าสุดแล้ว

สมมติเรามี array เปล่า แล้วใส่ค่าที่ index ติดลบ เช่น -5 จากนั้นเพิ่มค่าถัดไปด้วย $array[] = … ก่อน PHP 8.3 ค่าถัดไปจะกระโดดไปเริ่มที่ index 0 ส่วน PHP 8.3 นับต่อจาก -5 เป็น -4

$array = [];

$array[-5] = 'a';
$array[] = 'b';

var_export($array);

ผลลัพธ์ที่ได้ในแต่ละเวอร์ชัน

array (
  -5 => 'a',
  0 => 'b',
)

PHP 8.0 แก้เรื่องนี้ไปแล้วรอบหนึ่งสำหรับ array ที่ประกาศพร้อม key ติดลบ เช่น [-5 => 'a'] แต่ยังตกกรณีใส่ค่าลงใน array เปล่า ซึ่ง PHP 8.3 มาเก็บให้ครบ (UPGRADING ของ PHP 8.3)

คลาส anonymous ประกาศเป็น readonly ได้

PHP 8.2 ให้เราประกาศ readonly class ได้แล้ว แต่ยังใช้กับคลาส anonymous ไม่ได้ PHP 8.3 เติมส่วนนี้ให้

$class = new readonly class {
    public function __construct(
        public string $foo = 'bar',
    ) {}
};

$class->foo = 'baz'; // Error: Cannot modify readonly property class@anonymous::$foo

RFC

เช็กว่า string เป็น JSON ที่ถูกต้องด้วย json_validate()

ที่ผ่านมา ถ้าอยากรู้ว่า string เป็น JSON ที่ถูกต้องไหม เราต้อง json_decode() ทั้งก้อนแล้วดู json_last_error() PHP 8.3 เพิ่ม json_validate() ที่เช็กอย่างเดียว ไม่ต้องสร้าง array หรือ object ออกมา จึงกินหน่วยความจำน้อยกว่า

json_validate(string $json, int $depth = 512, int $flags = 0): bool
// ก่อน PHP 8.3
json_decode($json);
$isValid = json_last_error() === JSON_ERROR_NONE;

// PHP 8.3
$isValid = json_validate($json);

json_validate('{"name": "PHP"}'); // true
json_validate('{name: PHP}');     // false

RFC

เรียก class constant ด้วยชื่อที่อยู่ในตัวแปร

ถ้าชื่อ constant อยู่ในตัวแปร PHP 8.3 ให้เราเขียน Foo::{$name} ได้ตรง ๆ ไม่ต้องต่อ string แล้วส่งให้ constant()

class Foo
{
    const BAR = 'bar';
}

$name = 'BAR';

// ก่อน PHP 8.3
constant(Foo::class . '::' . $name); // 'bar'

// PHP 8.3
Foo::{$name}; // 'bar'

RFC

ของอื่นที่มากับ PHP 8.3

PHP 8.3 ยังเพิ่มเมธอดใหม่ใน Randomizer, ฟังก์ชัน mb_str_pad(), ตรวจจับ stack overflow และ deprecate ของเล็ก ๆ อีกหลายข้อ อ่านรายการเต็มได้ที่หน้า release ของ php.net และ php.watch

อ่านต่อ

ล่าสุด

ดูทั้งหมด →