İçeriğe geç
Muhammet Şafak
Diller 3 dk okuma

PHP 8.4 yolda: property hook'lar ve asimetrik görünürlük

PHP 8.4 ile gelen property hook'lar ve asimetrik görünürlük; bu eklemelerin sınıf modellemesini nasıl değiştireceği.


PHP 8.4 bu ayın sonunda yayımlanacak. Sürüm henüz çıkmadan beta üzerinde inceliyorum, çünkü 8.4 son yılların en dikkat çekici sürümlerinden biri: sınıfların property’lerini nasıl modellediğimizi gerçekten değiştirecek iki ekleme getiriyor.

Property hook’lar

Bugüne kadar bir özelliğin okunmasına ya da yazılmasına araya girmek istediğimizde getter/setter metotları yazıyorduk. Bu, basit bir alanı bile metot çiftine dönüştürüyor ve sınıfı şişiriyordu.

PHP 8.4 ile property hook geliyor: özelliğin kendisine, okunduğunda veya yazıldığında çalışacak mantık bağlayabiliyorsunuz:

class Kullanici
{
    public string $tamAd {
        get => $this->ad . ' ' . $this->soyad;
    }

    public string $eposta {
        set => strtolower(trim($value));
    }

    public function __construct(
        private string $ad,
        private string $soyad,
    ) {}
}

Burada $tamAd aslında saklanmıyor; okunduğunda hesaplanıyor. $eposta ise yazılırken normalleştiriliyor. Dışarıdan bakan kod yine düz bir özellik görüyor — $kullanici->eposta — ama araya mantık girebiliyor. Yıllarca getter/setter ile çözdüğüm şeyi, artık alanın kendisi anlatıyor.

Hook’ların interface’lerle birlikte çalışması

Property hook’ların özellikle fark yaratacağı alan, interface’ler. Interface’lerde hook imzaları tanımlanabiliyor:

interface Adlandirilabilir
{
    public string $tamAd { get; }
}

Bu, “bu sınıfın $tamAd özelliği okunabilir olmalı” sözleşmesini doğrudan interface’e taşıyor. Uygulayan sınıf ister gerçek bir alan saklasın, ister get hook’uyla hesaplasın — sözleşme ihlal edilmediği sürece fark etmez. Bunu daha önce dokümantasyon yorumuyla veya getName() gibi bir metot zorunluluğuyla sağlıyordum; şimdi dil bunu anlıyor.

Dikkat edilmesi gereken bir tuzak

set hook’u değeri özelliğe yazmaz; yazan siz oluyorsunuz. Eğer hook içinde $this->eposta = $value demezseniz özellik hiç atanmaz. Bu, C# veya Kotlin property’lerinden gelen birini şaşırtabilecek bir davranış:

public string $eposta {
    set {
        // Normalleştir ve SAKLAYı unutma:
        $this->eposta = strtolower(trim($value));
    }
}

Kısa ok sözdiziminde (set => strtolower(trim($value))) atama otomatik yapılıyor; yalnızca blok biçiminde { set { ... } } kullandığınızda elle yazmanız gerekiyor.

Asimetrik görünürlük

İkinci ekleme asymmetric visibility (asimetrik görünürlük). Bir özelliğin okunmasını ve yazılmasını ayrı görünürlük seviyelerine bağlayabiliyorsunuz:

class Siparis
{
    public private(set) string $durum = 'bekliyor';
}

Burada $durum dışarıdan okunabilir ama yalnızca sınıfın içinden değiştirilebilir. Daha önce bunun için özelliği private yapıp ayrı bir getter metodu yazmak gerekiyordu. Artık niyet — “herkes görebilir, kimse dışarıdan değiştiremez” — tek satırda ifade ediliyor.

protected(set) da kullanılabiliyor; yani alt sınıflar yazabilir ama dışarıya kapalı:

class Temel
{
    public protected(set) int $versiyon = 1;
}

class Alt extends Temel
{
    public function yuksel(): void
    {
        $this->versiyon++; // Geçerli
    }
}

$obj = new Alt();
echo $obj->versiyon; // 1 — okunabilir
$obj->versiyon = 5;  // Hata! Dışarıdan yazılamaz

Bu, PHP 8.1’de gelen readonly özelliklerinin biraz daha esnek kardeşi. readonly bir kez yazılabilir ve değiştirilemez; asimetrik görünürlük ise “kaç kez olursa olsun yalnızca içeriden yazılabilir” garantisi veriyor. İkisi farklı ihtiyaçlara cevap veriyor.

Bu ikisi birlikte ne anlatıyor

Property hook’lar ve asimetrik görünürlük, aynı yöne işaret ediyor: özellikleri yine basit özellik gibi kullanmak, ama gerektiğinde kontrolü kaybetmemek. Yıllardır bir alanı korumak ya da hesaplamak istediğimde sınıfı metotlarla şişiriyordum; çağıran kod da düz alan yerine metot görüyordu. 8.4, bu ödünü ortadan kaldırıyor.

Value object yazarken bu farkı en net hissediyorum. Daha önce Money gibi bir sınıfta getAmount(), getCurrency(), getFormatted() gibi getter zincirleri yazıyordum. Artık $money->amount, $money->currency, $money->formatted — okumak için metot yokken yazmak için kontrol var.

Sürüm çıkınca ilk yapacağım, değer nesnelerimdeki getter yığınını gözden geçirmek olacak. Çoğu, basit bir property hook’a inecek. Az kod, aynı garanti — bir dil sürümünden istediğim tam olarak bu.

readonly ile karşılaştırma

PHP 8.1’de gelen readonly özellikler ile property hook’ların asimetrik görünürlük özelliği arasında bir ayrım yapmak gerekiyor. readonly bir özellik constructor dışında yalnızca bir kez atanabiliyor ve sonrasında değiştirilemez — tam anlamıyla immutable. private(set) ile asimetrik görünürlük ise “içeriden istediğin kadar değiştir, dışarıdan el süremezsin” garantisi veriyor. İkisi farklı ihtiyaçları karşılıyor: value object için readonly, durumu yalnızca sınıf içinde kontrollü değiştirmek için private(set) daha uygun. Bu ayrımı bilmeden birini diğerinin yerine kullanmak, sonradan değişiklik gerektirdiğinde sizi köşeye sıkıştırıyor.

Etiketler: #PHP
Paylaş:

İlgili Yazılar

Sitede Ara

Yazı, proje ve sayfalarda arama yapmak için yazmaya başlayın.

Esc ile kapat Pagefind ile güçlendirildi