# 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.

- Yayın: 2024-11-03
- Kategori: Diller
- Etiketler: PHP
- Okuma süresi: 3 dk okuma
- Kaynak: https://www.muhammetsafak.com.tr/blog/php-8-4-yolda-property-hooklar-ve-asimetrik-gorunurluk/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
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:

```php
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:

```php
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ış:

```php
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:

```php
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ı:

```php
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](/blog/php-8-1-yolda-enumlar-ve-readonly-ile-daha-guvenli-modeller) 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.
