Lập trình PHP
figonkingx  

PHP 8.4 chính thức: Hướng dẫn nâng cấp và tính năng mới

PHP 8.4 đã chính thức phát hành vào ngày 21/11/2024, mang đến những tính năng được mong đợi nhất trong lịch sử PHP. Property hooks, asymmetric visibility, và nhiều cải tiến khác. Bài viết này hướng dẫn chi tiết và cách nâng cấp an toàn.

Nội dung chính

Property Hooks – Tính năng đáng chờ đợi nhất

Property hooks cho phép định nghĩa getter và setter trực tiếp trong property declaration, tương tự C# properties:

Cú pháp cơ bản

class User {
    // Property với cả get và set hooks
    public string $fullName {
        get => $this->firstName . ' ' . $this->lastName;
        set {
            [$this->firstName, $this->lastName] = explode(' ', $value, 2);
        }
    }
    
    private string $firstName;
    private string $lastName;
    
    // Validation trong set hook
    public string $email {
        set {
            if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
                throw new InvalidArgumentException("Invalid email: $value");
            }
            $this->email = strtolower($value);
        }
    }
    
    // Read-only với chỉ get hook
    public int $age {
        get => (new DateTime())->diff($this->birthDate)->y;
    }
    
    private DateTime $birthDate;
}

// Usage
$user = new User();
$user->fullName = "John Doe";
echo $user->firstName;  // John
echo $user->lastName;   // Doe

$user->email = "John@Example.COM";
echo $user->email;  // john@example.com

Property hooks với backing value

class Temperature {
    public float $celsius {
        get => ($this->fahrenheit - 32) * 5 / 9;
        set => $this->fahrenheit = ($value * 9 / 5) + 32;
    }
    
    public float $fahrenheit = 32.0;
}

$temp = new Temperature();
$temp->celsius = 100;
echo $temp->fahrenheit;  // 212

Interface với property hooks

interface Named {
    public string $name { get; }  // Chỉ yêu cầu readable
}

interface Writable {
    public string $data { get; set; }  // Yêu cầu cả read và write
}

class Product implements Named {
    public string $name {
        get => $this->internalName;
    }
    private string $internalName = "Default";
}

Asymmetric Visibility

Cho phép set visibility khác nhau cho read và write:

class BankAccount {
    // Public read, private write
    public private(set) float $balance = 0;
    
    // Public read, protected write
    public protected(set) string $accountNumber;
    
    public function deposit(float $amount): void {
        if ($amount <= 0) {
            throw new InvalidArgumentException("Amount must be positive");
        }
        $this->balance += $amount;
    }
    
    public function withdraw(float $amount): void {
        if ($amount > $this->balance) {
            throw new RuntimeException("Insufficient funds");
        }
        $this->balance -= $amount;
    }
}

$account = new BankAccount();
echo $account->balance;    // 0 - OK, public read
$account->deposit(100);
echo $account->balance;    // 100
// $account->balance = 1000;  // Error! private write

Kết hợp với readonly

class Order {
    // Chỉ có thể set trong constructor
    public readonly string $orderId;
    
    // Public read, private set (có thể thay đổi nội bộ)
    public private(set) string $status = 'pending';
    
    public function __construct() {
        $this->orderId = uniqid('ORD-');
    }
    
    public function confirm(): void {
        $this->status = 'confirmed';
    }
}

new MyClass()->method() Syntax

Không cần parentheses khi chain methods sau new:

// PHP 8.3
$result = (new StringBuilder())->append("Hello")->append(" World")->build();

// PHP 8.4 - Cleaner!
$result = new StringBuilder()->append("Hello")->append(" World")->build();

// Thực tế
$user = new UserDTO()->fromArray($data)->validate()->toJson();

$response = new JsonResponse()->setData($data)->setStatus(200)->send();

Các hàm mới

array_find() và array_find_key()

$users = [
    ['id' => 1, 'name' => 'Alice', 'age' => 25],
    ['id' => 2, 'name' => 'Bob', 'age' => 30],
    ['id' => 3, 'name' => 'Charlie', 'age' => 35],
];

// Tìm user đầu tiên >= 30 tuổi
$user = array_find($users, fn($u) => $u['age'] >= 30);
// ['id' => 2, 'name' => 'Bob', 'age' => 30]

// Tìm key
$key = array_find_key($users, fn($u) => $u['name'] === 'Charlie');
// 2

// Tương tự array_any() và array_all()
$hasAdults = array_any($users, fn($u) => $u['age'] >= 18);  // true
$allAdults = array_all($users, fn($u) => $u['age'] >= 18);  // true

mb_trim(), mb_ltrim(), mb_rtrim()

$text = " Hello World ";  // Japanese spaces
$trimmed = mb_trim($text);
// "Hello World"

$text2 = "---Hello---";
mb_ltrim($text2, "-");  // "Hello---"
mb_rtrim($text2, "-");  // "---Hello"

DOM HTML5 Support

// Trước: DOMDocument không hỗ trợ HTML5 đúng cách
// Sau: DOM\HTMLDocument với full HTML5 support

$dom = Dom\HTMLDocument::createFromString($html);
$dom = Dom\HTMLDocument::createFromFile('page.html');

// Modern DOM methods
$element = $dom->querySelector('.my-class');
$elements = $dom->querySelectorAll('div.container');
$element->classList->add('active');
$element->dataset['id'] = '123';

PDO Driver-specific Subclasses

// Trước: Generic PDO
$pdo = new PDO("mysql:...");

// Sau: Driver-specific với IDE support
$pdo = new Pdo\Mysql("mysql:host=localhost;dbname=test", "user", "pass");
$pdo = new Pdo\Pgsql("pgsql:host=localhost;dbname=test", "user", "pass");
$pdo = new Pdo\Sqlite("sqlite:database.db");

// MySQL-specific methods với type hints
$pdo->getWarningCount();  // MySQL only

Deprecated và Removed

Deprecated

  • session_set_save_handler() với objects không implement SessionHandlerInterface
  • Passing E_STRICT to error_reporting()
  • Một số mbstring functions với invalid encoding

Removed

  • implode() với separator sau array (đã deprecated từ 7.4)
  • Một số legacy IMAP functions

Hướng dẫn nâng cấp

1. Kiểm tra compatibility

# Cài đặt PHP 8.4
sudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt install php8.4 php8.4-cli php8.4-common

# Hoặc Docker
docker run -it php:8.4-cli php -v

2. Update dependencies

# Kiểm tra composer packages
composer why-not php 8.4

# Update packages
composer update

# Check for deprecations
./vendor/bin/phpstan analyse -l 6 src/

3. Test thoroughly

# Run tests với PHP 8.4
php8.4 vendor/bin/phpunit

# Check for warnings
php8.4 -d error_reporting=E_ALL your_script.php

Migration tips

// Trước: Manual getters/setters
class User {
    private string $email;
    
    public function getEmail(): string {
        return $this->email;
    }
    
    public function setEmail(string $email): void {
        $this->email = strtolower($email);
    }
}

// Sau: Property hooks (PHP 8.4)
class User {
    public string $email {
        get => $this->email;
        set => $this->email = strtolower($value);
    }
}

Fullstack Station Tips

PHP 8.4 là một major release đáng để nâng cấp. Những điểm nổi bật:

  • Property hooks – Modernize PHP, giảm boilerplate đáng kể
  • Asymmetric visibility – Immutable objects dễ dàng hơn
  • HTML5 DOM – Xử lý HTML hiện đại không cần hacks
  • Array functions – array_find() rất tiện cho daily work

Lời khuyên: Test kỹ trên staging trước khi upgrade production. Hầu hết breaking changes đã được deprecated từ 8.2/8.3 nên upgrade path khá smooth.

Tham khảo

Comments

Leave A Comment