PHP 8.3 ve 8.4 Yenilikleri: Tip Sistemi Rehberi

PHP 8.3 ve 8.4, dilin tip sistemi ve okunabilirlik tarafında önemli eklemeler getirdi. Bu rehber, orta seviye geliştiricilerin bu sürümlerdeki yenilik...

PHP 8.3 ve 8.4 Yenilikleri: Tip Sistemi Rehberi

PHP 8.3 ve 8.4, dilin tip sistemi ve okunabilirlik tarafında önemli eklemeler getirdi. Bu rehber, orta seviye geliştiricilerin bu sürümlerdeki yenilikleri günlük kodlarına nasıl uygulayabileceğini ve performans değerlendirmesini nasıl yapacağını ele alıyor.

Kapsam ve Önkoşullar

  • PHP 8.3 ve 8.4 sürümlerine odaklanılmıştır. PHP 8.3, 8.4'ün temelini oluşturur; 8.4'te 8.3'te eklenen özelliklerin çoğu korunur.
  • Örnekler PHP 8.3+ söz dizimini varsayar. Daha eski bir sürümde çalıştırırsanız söz dizimi hataları alırsınız.
  • Performans testleri için gerçek sayısal sonuçlar burada verilmemiştir. Sürümler arası performans farkı; iş yüküne, uzantılara, opcache yapılandırmasına ve JIT ayarlarına göre değişir. Kendi ortamınızda ölçüm yapmanız gerekir.

PHP 8.3'ün Öne Çıkan Özellikleri

Typed Class Constants (Tipli Sınıf Sabitleri)

PHP 8.3 öncesinde sınıf sabitlerine tür belirtilemiyordu. 8.3 ile sabitlere tür ekleyebilirsiniz:

class Status
{
    public const string ACTIVE = 'active';
    public const int MAX_RETRY = 3;

    // Alt sınıf bu sabiti uyumsuz bir türle geçersiz kılamaz.
    public const string ARCHIVED = 'archived';
}

Beklenen davranış: Sabitin değeri, belirtilen türle uyuşmazsa çalışma zamanında TypeError alırsınız. Bu özellikle kalıtımda sabit tutarlılığını korumak için kullanışlıdır.

Dinamik Sınıf Sabiti Erişimi

8.3 ile sabitlere dinamik olarak, ::{$name} söz dizimiyle erişilebilir:

class Config
{
    public const string ENV = 'production';
}

$name = 'ENV';
echo Config::{$name}; // production

Not: Dinamik erişim, statik analiz araçlarının sabiti çözümlemesini zorlaştırabilir. Sabit adını kullanıcı girdisinden türetmeyin.

json_validate()

JSON doğrulaması için json_decode() çağırıp sonucu kontrol etmek yerine, yalnızca geçerlilik kontrolü yapan bir fonksiyon geldi:

$payload = '{"id": 1, "name": "test"}';

if (json_validate($payload)) {
    $data = json_decode($payload, true);
}

Beklenen davranış: json_validate() yalnızca true/false döner; çözümlenmiş veriyi vermez. Yalnızca geçerlilik kontrolü gerekiyorsa bellek açısından daha verimlidir. Veriyi de kullanacaksanız doğrudan json_decode() yapıp hata kontrolü yapmak daha mantıklıdır.

#[\Override] Niteliği

Bir metodun üst sınıftaki metodu gerçekten geçersiz kıldığını derleme zamanında doğrular:

class Base
{
    public function run(): void {}
}

class Child extends Base
{
    #[\Override]
    public function run(): void {}
}

Beklenen davranış: Üst sınıfta run() yoksa ya da imza uyuşmuyorsa hata alırsınız. Yeniden adlandırma sırasında sessizce kırılan override'ları yakalamak için değerlidir.

readonly Sınıflar ve Klonlama İyileştirmesi

PHP 8.2'de gelen readonly sınıflar 8.3'te klonlama sırasında değiştirilebilir hale geldi: __clone içinde readonly özellikler yeniden atanabilir. Bu, klon üzerinde ayar değiştirmek isteyen kalıpları mümkün kılar.

PHP 8.4'ün Öne Çıkan Özellikleri

Property Hooks

8.4'ün en büyük yeniliği. Özelliklere get ve set davranışı doğrudan tanımlanabilir; ayrı getter/setter metotlarına gerek kalmaz:

class User
{
    public string $fullName {
        get => $this->firstName . ' ' . $this->lastName;
        set (string $value) {
            [$this->firstName, $this->lastName] = explode(' ', $value, 2);
        }
    }

    public function __construct(
        private string $firstName,
        private string $lastName,
    ) {}
}

Beklenen davranış: $user->fullName okunduğunda get bloğu, atandığında set bloğu çalışır. Sanal özellikler (arkasında gerçek bir alan olmayan) ve hesaplanan özellikler için kullanışlıdır.

Dikkat: set bloğunda özyinelemeli atama yapmayın; aksi halde sonsuz döngü oluşur. Sanal bir özellikte $this->fullName = $value yazmak bu tuzağa örnektir.

Asimetrik Görünürlük

Bir özelliğin okunması ve yazılması farklı görünürlükte olabilir:

class Wallet
{
    public private(set) int $balance = 0;

    public function deposit(int $amount): void
    {
        $this->balance += $amount;
    }
}

Beklenen davranış: Dışarıdan $wallet->balance okunabilir, ancak yalnızca sınıf içinden yazılabilir. readonly'ye göre daha esnek bir kapsülleme sağlar; çünkü sınıf içi değişiklik serbesttir.

new İfadesini Zincirleme

Parantezsiz zincirleme artık mümkün:

// 8.4 öncesi
$name = (new ReflectionClass('Foo'))->getShortName();

// 8.4
$name = new ReflectionClass('Foo')->getShortName();

Beklenen davranış: Metot çağrısı, örnekleme sonrası doğrudan zincirlenebilir. Okunabilirliği artırır, davranışı değiştirmez.

array_find, array_find_key, array_any, array_all

Dizi üzerinde koşul arayan yardımcı fonksiyonlar geldi:

$numbers = [1, 3, 4, 7];

$firstEven = array_find($numbers, fn(int $n) => $n % 2 === 0); // 4
$keyOfFirstEven = array_find_key($numbers, fn(int $n) => $n % 2 === 0); // 2
$hasEven = array_any($numbers, fn(int $n) => $n % 2 === 0); // true
$allPositive = array_all($numbers, fn(int $n) => $n > 0); // true

Beklenen davranış: array_find eşleşme yoksa null döner. array_find_key eşleşme yoksa null döner; anahtar 0 olabileceği için sonucu null kontrolüyle değerlendirin, isset() veya falsy kontrolüyle değil.

Performans Değerlendirmesi

Sürümler arası performans karşılaştırması yaparken şu noktalara dikkat edin:

  • OpCache ve JIT: Üretimdeki performansın büyük kısmı OpCache ve JIT yapılandırmasına bağlıdır. Testleri bu katmanı açık ve kapalı olarak ayrı çalıştırın.
  • İş yükü tipi: CPU yoğun döngüler, I/O yoğun uygulamalar ve tip ağırlıklı kodlar farklı davranır. Sentetik benchmark sonuçları gerçek uygulamayı temsil etmeyebilir.
  • Uzantılar: Kullanılan eklentilerin sürümleri ve 8.4 uyumluluğu sonucu doğrudan etkiler.
  • Ölçüm aracı: Tutarlı bir araç seçin (örneğin kendi uygulamanıza dayalı senaryo testleri). Tek bir fonksiyonun mikro benchmark'ı, uygulama geneli için yanıltıcı olur.

Güvenilir bir karşılaştırma için aynı donanımda, aynı yapılandırmayla, birden çok tekrarda medyan değerleri karşılaştırın. Tek bir çalıştırmanın sonucunu kesin bilgi olarak sunmayın.

Yaygın Hatalar

  • Typed constant tür uyuşmazlığı: Sabit değeri ile belirtilen tür uyuşmazsa TypeError alırsınız. Değerleri sabit tanımında doğrulayın.
  • Property hook özyinelemesi: Sanal bir özelliğin get/set bloğunda aynı özelliğe erişmek sonsuz döngü yaratır. Arka plandaki gerçek alanı kullanın.
  • array_find sonucunu falsy kontrolle değerlendirmek: Dönen değer 0, '' veya false olabilir. Eşleşme yokluğunu yalnızca null ile ayırt edin.
  • json_validate ile json_decode'u gereksiz iki kez çağırmak: Veriyi kullanacaksanız tek geçiş yeterlidir.
  • Sürüm karışıklığı: 8.4 özelliklerini 8.3 ortamında çalıştırmaya çalışmak söz dizimi hatası verir. composer.json içindeki php kısıtını ve CI matrisini gerçek hedef sürüme göre ayarlayın.

Güvenlik Etkileri

  • Dinamik sabit erişimi: Sabit adını kullanıcı girdisinden türetmek, beklenmeyen sabitlere erişime yol açabilir. Adları yalnızca sabit bir listeden seçin.
  • Property hook içinde doğrulama: set bloklarını girdi doğrulaması için kullanabilirsiniz; ancak doğrulamayı tek savunma katmanı yapmayın. Sınır katmanında da doğrulayın.
  • Asimetrik görünürlük: private(set) yalnızca dil seviyesinde bir kısıtlamadır; yansıma (reflection) ile aşılabileceğini unutmayın. Kritik değerleri ayrıca iş kuralı katmanında koruyun.
  • #[\Override]: Güvenlik sağlamaz; yalnızca geliştirme zamanı doğruluğu içindir.

Geçiş İçin Pratik Adımlar

  1. Hedef sürümü belirleyin ve composer.json içindeki php kısıtını buna göre güncelleyin.
  2. CI matrisine PHP 8.3 ve 8.4'ü ekleyin; testleri her iki sürümde çalıştırın.
  3. Statik analiz aracınızı (örneğin PHPStan, Psalm) güncel sürüme yükseltin; yeni söz dizimini tanıması gerekir.
  4. Kullanılan eklentilerin sürüm uyumluluğunu kontrol edin.
  5. Yeni özellikleri önce izole modüllerde deneyin; üretime kademeli alın.
  6. Performans karşılaştırmasını kendi ortamınızda, kontrollü koşullarda yapın.

PHP 8.3 ve 8.4, günlük kod kalitesini artıran eklemeler sunuyor. Tip güvenliği, kapsülleme ve dizi işlemleri tarafındaki bu yenilikler, doğru kullanıldığında hem okunabilirliği hem de bakım maliyetini iyileştirir. Performans beklentilerinizi ise genel geçer iddialar yerine kendi ölçümlerinizle şekillendirin.

İLGİLİ İÇERİKLER

Bunları da Okumak İsteyebilirsiniz