<

PHP 8.2 ile Modern Backend: Neler Değişti, Neden Yükseltmelisiniz?

Geçen ay devir aldığımız bir projenin sunucusuna bağlandık: PHP 5.6. Yıl 2023, sürüm 5.6 — yani sekiz yıl önce çıkmış, dört buçuk yıldır tek bir güvenlik yaması almamış bir motor, canlıda müşteri verisi işliyor. İşin ilginci, müşteri durumdan habersizdi; "sistem çalışıyor" diye biliyordu. Çalışıyordu da. Kapısı açık bir dükkân da gayet iyi çalışır, biri içeri girene kadar.

Bu manzara maalesef istisna değil. PHP hâlâ web'in kabaca dörtte üçünü çalıştırıyor ama sahadaki kurulumların ciddi bir kısmı 5.6 veya 7.x serisinde takılı duruyor. Oysa 8.x ile PHP bambaşka bir dil oldu. Bu yazıda hem 8.2'nin somut getirilerini hem de yükseltmenin nasıl kazasız yapılacağını anlatacağım — ikisi de aynı derecede önemli çünkü.

8.2'de işimize gerçekten yarayan şeyler

Sürüm notu listelemenin âlemi yok; ben günlük işimizde karşılığını gördüğümüz maddeleri sayayım:

  • Readonly sınıflar: Sınıfın tüm özelliklerini tek kelimeyle değişmez yapıyorsunuz. DTO'lar ve value object'ler için biçilmiş kaftan — "bu nesneyi kim, nerede değiştirdi?" avcılığı tarihe karışıyor.
  • Bağımsız null, true, false tipleri: Artık bir metodun dönüş tipi tek başına false veya null olabiliyor. API sözleşmeleri netleşiyor; "başarısızsa false döner" cümlesi artık tip sisteminin garantisi.
  • #[\SensitiveParameter]: Bu öznitelikle işaretlenen parametreler stack trace'te maskeleniyor. Hata ayıklama loguna müşteri şifresinin düştüğü vakaları gören biri olarak: küçük görünen, kritik özellik.
  • Performans: 7.4'ten 8.2'ye taşıdığımız projelerde, hiçbir kod optimizasyonu yapmadan, gerçek dünya yükünde yüzde 15-30 arası hızlanma ölçtük. Aynı donanım, aynı kod, daha kısa yanıt süreleri.

Bunların dışında enum'lar, constructor property promotion, match ifadesi gibi 8.0-8.1 mirası da cabası — 5.6'dan veya 7.2'den bakan biri için 8.2, aynı dilin uzak bir akrabası gibi görünecektir. İyi anlamda.

Madalyonun öbür yüzü: 8.2 bazı eski alışkanlıkları da resmen emekliye ayırıyor. En çok konuşulanı dinamik özellikler — sınıfta tanımlanmamış bir özelliğe değer atamak artık deprecated. Modern kod için sorun değil ama legacy projelerde, özellikle "nesneye o an aklına gelen alanı yapıştır" usulüyle yazılmış kodlarda, uyarı yağmuruna hazır olun. Uyarı dediğime bakmayın; bunlar gelecek sürümde hataya dönüşecek sinyaller, yani yükseltme planının bir parçası olarak şimdiden temizlenmeleri gerek.

Eski sürümde kalmanın faturası her ay kesiliyor

"Çalışan sisteme dokunma" felsefesini anlıyorum; biz de gereksiz dokunuşun karşısındayız. Ama burada dokunmamanın kendisi risk.

Birincisi güvenlik: PHP 7.4'ün güvenlik desteği geçen kasımda bitti. Bugün 7.4 ve altında çalışan her sistem, bundan sonra keşfedilecek hiçbir açığa yama almayacak demek. Açık keşfedildiğinde (ki keşfediliyor) tek seçeneğiniz aceleyle, plansızca, yangın ortamında sürüm atlamak olacak — yani yükseltmenin en pahalı ve en riskli biçimi.

İkincisi ekosistem: modern kütüphaneler eski PHP'yi hızla terk ediyor. Framework'lerin güncel sürümleri, ödeme sağlayıcılarının SDK'ları, API istemcileri... Her biri minimum sürüm şartını yukarı çektikçe, eski sürümdeki projeniz güncellemelerden koparak yaşamaya başlıyor. Teknik borç faiziyle birlikte büyüyor.

Üçüncüsü insan tarafı — bunu kimse konuşmuyor ama gerçek: iyi geliştiriciler legacy PHP'de çalışmak istemiyor. Eski sürümde kalan proje, ekip bulmakta da zorlanıyor.

Yazının başındaki 5.6 projesine dönersek: müşteriyle oturup iki senaryonun maliyetini yan yana koyduk. Planlı yükseltme — testleriyle, kademeli geçişiyle — birkaç haftalık kontrollü bir çalışma. Alternatif senaryo, yani bir gün açık yüzünden veri ihlali yaşamak: KVKK bildirimi, olası idari ceza, müşteri kaybı, itibar onarımı ve yine aynı yükseltmenin bu kez yangın ortamında yapılması. Tabloyu gören müşteri kararı beş dakikada verdi. Yükseltme pahalı görünür; ta ki yapmamanın fiyatını yan sütuna yazana kadar.

Kazasız yükseltmenin dört adımı

Şimdi işin mutfağı. Bizim defalarca uyguladığımız ve artık standartlaştırdığımız sıra şu.

Önce test güvencesi: kritik iş akışlarını (giriş, sipariş, ödeme, rapor) kapsayan smoke testler yazın. Kapsamlı test paketi şart değil — olsa harika olurdu ama legacy projede gerçekçi değil; "sistem ayakta mı ve para akışı çalışıyor mu" sorusuna hızlı cevap veren bir set yeterli başlangıç.

Sonra statik analiz: PHPStan'i projeye bağlayıp hedef sürümle uyumsuz kullanımları koşmadan görün. Kaldırılmış fonksiyonlar, değişen imzalar, tip uyumsuzlukları — bunların listesini üretimde hata olarak değil, analiz raporunda satır olarak görmek istersiniz. Rector gibi araçlar dönüşümün bir kısmını otomatik de yapabiliyor.

Statik analiz aşamasına bir madde daha ekleyin: bağımlılıklar. Sizin kodunuz 8.2'ye hazır olsa bile, composer.json'daki paketlerin her biri aynı şeyi söyleyemeyebilir. Yükseltme planına başlarken paket listesini dökün, hangilerinin 8.2 desteklediğini, hangilerinin terk edilmiş olduğunu işaretleyin. Terk edilmiş paket çıkarsa (çıkıyor, hem de sık), alternatifine geçiş de yükseltme projesinin kapsamına girer — bunu ortasında keşfetmek yerine başında bilmek, takvimi gerçekçi kurmanın tek yolu.

Üçüncü adım kademeli geçiş: 5.x veya 7.x'ten doğrudan 8.2'ye atlamak yerine, 8.1'de deprecated uyarılarını temizleyip 8.2'ye öyle geçmek çok daha kontrollü ilerliyor. Her adımda ne kırıldığını biliyorsunuz; tek dev sıçramada ise hata ayıklama samanlıkta iğne aramaya dönüyor.

Dördüncüsü, davranış değişikliği avı — en sinsi kısım bu. Mesela PDO'nun hata modu 8.0'dan itibaren varsayılan olarak exception fırlatıyor; eskiden sessizce false dönen sorgu artık uygulamayı durduruyor. Yükseltme sonrası "beyaz ekran" vakalarının bir numaralı sebebi bu tür sessiz varsayılan değişiklikleri. Sürüm notlarındaki "backward incompatible changes" bölümü, yükseltme projesinin gerçek şartnamesidir; üşenmeden okunacak.

Operasyon tarafına da bir paragraf borçluyum. Yükseltmeyi "sunucuda PHP'yi güncelle, hayırlısını bekle" diye yapmıyoruz; yeni sürüm ayrı bir ortamda (container veya ayrı FPM havuzu) kurulur, trafik önce küçük bir yüzdeyle oraya verilir, hata oranları ve yanıt süreleri izlenir, sorun görülmezse kademeli artırılır. Geri dönüş yolu her an açık tutulur. Bu düzen kulağa fazla ihtiyatlı gelebilir; ama gece yarısı "eski sürüme nasıl dönüyorduk?" sorusunu panikle aramaktansa, planı baştan yazmak her zaman ucuz.

Bekleyenlere küçük bir not

"8.3 zaten yıl sonunda geliyor, onu bekleyelim" diyenler çıkacak. Beklemeyin. Sürüm yarışının bir sonu yok; siz 8.3'ü beklerken 8.4 duyurulacak. Kritik olan güncel ve desteklenen banda girmek; oradan sonraki küçük sıçramalar, ilk büyük sıçramanın yanında çocuk oyuncağı.

Elinizde yıllardır süründürülen bir legacy proje varsa ve "nereden başlasak" diyorsanız, iletişime geçin — önce mevcut durumu çıkarıp riskleriyle birlikte önünüze koyalım, yükseltme yol haritasını ondan sonra birlikte çizelim. O 5.6 projesini de bu yöntemle, müşterinin tek gün kesinti yaşamadığı bir planla taşıyoruz şu an. Yapılabiliyor; yeter ki plansız yapılmasın.

📅 Yayınlanma:  ·  Yakup Zengin