# 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 ve readonly ile karşılaştırması.

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

---
> **Kısaca:** PHP 8.4 sınıf modelleme biçimini değiştiren iki özellik getiriyor: property hook okuma ve yazma mantığını özelliğe bağlıyor, asimetrik görünürlük okuma ve yazma kapsamını ayırıyor. Yazı ikisini örneklerle, set hook tuzağıyla ve readonly'den farkıyla anlatıyor.

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.

## PHP 8.4'te property hook nedir?

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 kılavuzunun property hook sayfası](https://www.php.net/manual/en/language.oop5.property-hooks.php), ok ifadesiyle yazılan bir set hook için "The value the expression evaluates to will be set on the backing value." diyor.

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.

## PHP 8.4'te asimetrik görünürlük nedir?

İkinci ekleme **asymmetric visibility (asimetrik görünürlük)**. [PHP kılavuzunun görünürlük sayfası](https://www.php.net/manual/en/language.oop5.visibility.php) şöyle diyor: "As of PHP 8.4, object properties may also have their visibility set asymmetrically, with a different scope for reading (get) and writing (set)." 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](/tr/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 yalnızca bir kez, tanımlandığı kapsamdan ilklendirilebiliyor 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.

---

### Kaynaklar

- [PHP 8.4 sürüm sayfası, erişim 2026-10-07](https://www.php.net/releases/8.4/en.php)
- [PHP kılavuzu: Property hooks, erişim 2026-10-07](https://www.php.net/manual/en/language.oop5.property-hooks.php)
- [PHP kılavuzu: Visibility, erişim 2026-10-07](https://www.php.net/manual/en/language.oop5.visibility.php)
