Pernah nggak sih kamu lagi nulis kode PHP, terus mikir "ini harusnya bisa lebih simpel"? Itu yang saya rasakan setiap kali bikin getter/setter manual di class PHP. Nah, PHP 8.4 akhirnya dengerin keluhan kita. Dirilis pada November 2024, versi ini bawa perubahan yang cukup signifikan buat cara kita nulis kode sehari-hari.
Saya sudah pakai PHP 8.4 di beberapa project sejak awal 2025, dan jujur saja ada beberapa fitur yang bikin saya nggak mau balik ke PHP 8.2 lagi. Di artikel ini, saya akan bahas fitur-fitur terbaiknya dengan contoh kode yang bisa langsung kamu copy-paste ke project.
Property Hooks - Getter dan Setter Tanpa Boilerplate
Ini dia fitur yang paling saya tunggu. Sebelum PHP 8.4, kalau kamu mau bikin property dengan validasi atau logika tambahan, kamu harus tulis getter dan setter secara manual:
// Sebelum PHP 8.4 - ribet banget
class User {
private string $name;
private string $email;
public function getName(): string {
return $this->name;
}
public function setName(string $value): void {
if (empty(trim($value))) {
throw new \InvalidArgumentException('Nama tidak boleh kosong');
}
$this->name = trim($value);
}
public function getEmail(): string {
return strtolower($this->email);
}
}
Sekarang dengan Property Hooks, semua itu bisa ditulis dalam beberapa baris:
// PHP 8.4 - clean dan singkat
class User {
public string $name {
set {
if (empty(trim($value))) {
throw new \InvalidArgumentException('Nama tidak boleh kosong');
}
$this->name = trim($value);
}
}
public string $email {
get => strtolower($this->email);
}
}
// Pemakaian
$user = new User();
$user->name = ' Budi Santoso '; // otomatis di-trim
echo $user->name; // "Budi Santoso"
$user->email = '[email protected]';
echo $user->email; // "[email protected]"
Yang bikin fitur ini powerful adalah hook-nya bisa di-abstract di interface atau parent class. Jadi kamu bisa definisikan contract-nya di satu tempat dan implementasi di subclass:
interface HasSlug {
public string $title { get; }
public string $slug {
get => strtolower(str_replace(' ', '-', $this->title));
}
}
class Article implements HasSlug {
public function __construct(
public string $title { get => $this->title; }
) {}
}
$artikel = new Article('Belajar PHP 8.4');
echo $artikel->slug; // "belajar-php-8.4"
Asymmetric Visibility - Read Public, Write Private
Ini fitur yang sering dibutuhkan di domain-driven design. Kamu mau property bisa di-read dari luar class, tapi hanya bisa di-write dari dalam class itu sendiri:
class Order {
public function __construct(
public private(set) string $status = 'pending',
public private(set) float $total = 0,
public private(set) DateTimeImmutable $createdAt,
) {
$this->createdAt = new DateTimeImmutable();
}
public function process(): void {
// Di dalam class, bisa update
$this->status = 'processing';
$this->total += 100;
}
}
$order = new Order();
echo $order->status; // "pending" - bisa di-read
echo $order->total; // 0 - bisa di-read
$order->status = 'done'; // ERROR! Hanya bisa di-write dari dalam class
Ini sangat berguna untuk immutable objects dan API responses. Kamu expose data tanpa takut diubah sembarangan dari luar. Di Laravel, ini cocok banget untuk Eloquent model yang mau kamu protect dari accidental mutation.
Array Functions Baru yang Kita Butuhkan Sejak Dulu
PHP 8.4 nambahin beberapa array function yang seharusnya sudah ada dari dulu. Yang paling sering saya pakai:
array_find() - cari elemen pertama yang match condition:
$users = [
['name' => 'Budi', 'age' => 17],
['name' => 'Andi', 'age' => 22],
['name' => 'Citra', 'age' => 19],
];
// Cari user pertama yang umurnya >= 18
$dewasa = array_find($users, fn($user) => $user['age'] >= 18);
// ['name' => 'Andi', 'age' => 22]
// Sebelumnya harus pakai foreach atau array_filter + reset
array_find_key() - cari key-nya, bukan value-nya:
$config = [
'debug' => false,
'cache' => true,
'maintenance' => true,
];
// Cari key pertama yang value-nya true
$key = array_find_key($config, fn($v) => $v === true);
// "cache"
array_any() dan array_all() - pengecekan kolektif:
$permissions = ['read', 'write', 'delete'];
// Apakah ada permission 'admin'?
$hasAdmin = array_any($permissions, fn($p) => $p === 'admin');
// false
// Apakah semua permission valid?
$validPerms = ['read', 'write', 'delete', 'admin'];
$allValid = array_all($permissions, fn($p) => in_array($p, $validPerms));
// true
Sebelumnya kamu harus kombinasi array_filter, count, dan array_search. Sekarang satu baris selesai.
Lazy Object Initialization
PHP 8.4 nambahin kemampuan bikin lazy objects yang baru di-initialize kalau benar-benar dipakai. Ini game-changer buat dependency injection container:
class DatabaseConnection {
public function __construct() {
// Koneksi ke database - mahal!
echo "Connecting to database...
";
sleep(1);
}
public function query(string $sql): array {
return ['result'];
}
}
// Lazy object - belum di-initialize
$db = new \ReflectionClass(DatabaseConnection::class)->newLazyProxy(
fn() => new DatabaseConnection()
);
// Belum ada "Connecting to database..."
echo "App started
";
// Baru di-initialize saat method pertama kali dipanggil
$result = $db->query("SELECT * FROM users");
// Output: "Connecting to database..." lalu query dijalankan
Kalau kamu pakai Laravel atau framework lain yang heavy di dependency injection, ini bisa percepat boot time aplikasi secara signifikan. Service yang nggak dipakai di request tertentu nggak perlu di-initialize.
Deprecated: Implicit Float to Int Conversions
PHP 8.4 mulai keras soal implicit conversion dari float ke int. Ini penting buat diwaspadai biar nggak kena warning mendadak:
// PHP 8.3: ini nggak error, tapi hasilnya unpredictable
$harga = 99.99;
$index = $harga; // implicit conversion, PHP truncate ke 99
// PHP 8.4: ini trigger deprecation notice
$index = $harga; // Deprecated: implicit conversion from float 99.99 to int
// Fix: eksplisit pakai (int) atau round()
$index = (int) $harga; // 99 - truncate
$index = (int) round($harga); // 100 - pembulatan
$index = (int) floor($harga); // 99 - bawah
$index = (int) ceil($harga); // 100 - atas
Kalau kamu punya codebase lama yang banyak pakai float-to-int conversion, jalankan php -d error_reporting=E_ALL artisan serve dan check log-nya. Lebih baik fix sekarang daripada pas upgrade ke PHP 9 nanti langsung error.
#[\Deprecated] Attribute
Sekarang kamu bisa tandai function, method, atau class yang sudah deprecated langsung di kode:
class UserService {
#[\Deprecated('Gunakan findByEmail() instead', since: '2.0')]
public function getUserByEmail(string $email): ?User {
return $this->findByEmail($email);
}
public function findByEmail(string $email): ?User {
// implementasi baru
}
}
// Pemakaian - PHP otomatis kasih warning
$service = new UserService();
$user = $service->getUserByEmail('[email protected]');
// Deprecated: Method UserService::getUserByEmail() is deprecated,
// gunakan findByEmail() instead (since 2.0)
Ini jauh lebih clean daripada nambahin comment @deprecated yang cuma bisa dideteksi oleh IDE. Sekarang PHP runtime sendiri yang kasih tahu developer kalau mereka pakai method yang sudah usang.
Cara Upgrade ke PHP 8.4
Kalau kamu pakai Ubuntu/Debian, upgrade cukup straightforward:
# Tambah PPA repository
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
# Install PHP 8.4
sudo apt install php8.4 php8.4-fpm php8.4-mysql php8.4-curl php8.4-mbstring php8.4-xml php8.4-zip php8.4-gd php8.4-intl -y
# Cek versi
php -v
# Update nginx config kalau pakai FPM
# Ganti php8.1-fpm.sock atau php8.2-fpm.sock ke php8.4-fpm.sock
sudo nano /etc/nginx/sites-available/your-site.conf
sudo systemctl restart php8.4-fpm
sudo systemctl restart nginx
Penting: sebelum upgrade di production, jalankan dulu di local atau staging. Cek kompatibilitas package yang kamu pakai di composer.json. Beberapa package lama mungkin belum support PHP 8.4.
# Cek kompatibilitas composer packages
composer update --dry-run 2>&1 | grep -i "php"
# Jalankan test suite setelah upgrade
php artisan test
# atau
./vendor/bin/phpunit
Dampak ke Framework Populer
Laravel 11+ sudah full support PHP 8.4. Property hooks bisa dipakai di Eloquent models untuk computed attributes tanpa accessor/mutator boilerplate. Laravel juga mulai leverage asymmetric visibility di internal classes.
CodeIgniter 4 kompatibel dengan PHP 8.4 sejak versi 4.4+. Kalau kamu pakai CI4, pastikan versi framework-nya sudah di-update. Property hooks bisa dipakai di Model untuk validasi data sebelum insert.
Symfony 7.2+ juga sudah adopt fitur-fitur baru ini, terutama di bagian dependency injection container yang pakai lazy objects.
Kesimpulan
PHP 8.4 bukan sekadar update minor. Property Hooks dan Asymmetric Visibility mengubah cara kita bikin class di PHP. Array functions baru bikin manipulasi data lebih ekspresif. Dan lazy objects bisa percepat aplikasi yang heavy di dependency injection.
Kalau kamu masih di PHP 8.1 atau 8.2, sekarang waktu yang tepat buat upgrade. Fitur-fitur ini bukan gimmick, tapi benar-benar bikin kode lebih readable dan maintainable. Saya pribadi sudah migrate 3 project ke PHP 8.4 dan nggak ada masalah kompatibilitas sama sekali.
Kamu sudah coba PHP 8.4 belum? Fitur mana yang paling kamu tunggu? Share di kolom komentar ya!