PHP 8.2 — yeniliklere hızlı bakış

İzni Burak Demirtaş
5 min readOct 27, 2022

24 Kasım 2022 tarihinde PHP 8.2 versiyonunun kararlı sürümünün yayınlanması bekleniyor. Bu yazımızda PHP’nin yeni sürümü için yapılan yenilikleri ve iyileştirmeleri inceleyeceğiz.

PHP 8.2

Son yıllarda PHP ekosistemi çok hareketli ve yapılan güzel gelişmeler sayesinde çok daha iyi bir hale geldi. Daha önceki yazılarımı okuyarak, önceki gelişmelere de göz atabilirsiniz:

PHP 8.2 ile birlikte bu gelişmelerin üzerine, yine oldukça faydalı birçok yeniliği kullanabileceğiz. Hadi şimdi bu yeniliklere göz atalım.

Read-Only Classes

Bildiğiniz gibi PHP 8.1 ile birlikte hayatımıza Read-Only Properties özelliği girmişti. Bu versiyonda bunu bir tık daha ileri götürüp, Read-Only Class özelliğini geliştirmişler. Bir örnek ile inceleyelim:

readonly class User
{
public function __construct(
public string $username,
public string $email,
public string $phone
) {}
}

Yazmış olduğumuz sınıf (class) ile bir instance (örnek) oluşturduğumuzda, bu sınıfın özelliklerine (property) erişebiliriz ama değerlerini değiştiremeyiz. Bunu yapmaya kalktığımızda bizi bir hata mesajı karşılıyor.

Konuyla alakalı RFC’ye buradan ulaşabilirsiniz.

Deprecate Dynamic Properties

Bu sürümdeki en kritik değişikliklerden biri çünkü önceki sürümlerde çalışan uygulamalarınız bu sürüm itibariyle uyarılar vermeye başlayabilir. Bu özellik ile sınıflar (class) içerisinde dinamik olarak bir özellik (property) tanımlanabilmesi artık desteklenmemeye başlanmış. Bildiğiniz gibi şu ana kadar, oluşturduğumuz sınıflara dinamik olarak var olmayan bir property ekleyebiliyorduk:

class User
{
public string $name;
}
$user = new User;
$user->email = 'burak@example.com'; // Uyarı verecek

Eğer sınıflarınızın içerisinde __get ve __set magic metotlarını kullanıyorsanız, her şey beklenildiği gibi çalışmaya devam edecek. Ve zaten bundan sonraki süreçte önerilen yöntem de bu:

class User
{
private array $properties = [];
public function __set(string $property, mixed $value): void
{
$this->properties[$property] = $value;
}
public function __get(string $property): mixed
{
return $this->properties[$property] ?? null;
}
}
$user = new User;
$user->email = 'burak@example.com'; // Uyarı vermeyecek
echo $user->email; // Değere erişebilecek

Sonraki sürümlere hazırlık için dynamic property kullandığınız sınıflar varsa şimdiden uygun hale getirmek mantıklı olabilir. Şimdiden refactorlere başlayalım :)

Konuyla alakalı RFC’ye buradan ulaşabilirsiniz.

`null`, `true`, and `false` as standalone types

Bildiğiniz gibi türler (types) PHP 7'den itibaren hayatımıza daha fazla girmeye başladı. Öncelikle parametre türleri (function parameter types) genişletildi, sonra dönüş tipleri (return types) eklendi ve daha sonra sınıf özelliklerinde (class properties) tür belirlemesi yapabilir hale geldik. Hatta birden fazla tür belirtebildiğimiz union type da desteklenmeye başladı. Bu konu hakkında detaylı örnekleri yukarda paylaşmış olduğumuz önceki yazılarda bulabilirsiniz.

PHP 8.2 ile birlikte null , true ve false değerlerini de bir tür (type) olarak kullanabileceğiz:

strpos(/* ... */): int|false

Built-in functionlar için bu tarz bir tanımlama söz konusu olacak. Kendi yazdığımız fonksiyonlarda da bu türleri kullanabileceğiz:

function foo(): false
{
return false;
}

Konuyla alakalı RFC ye buradan ulaşabilirsiniz.

Disjunctive Normal Form Types

Kısaca “DNF Types” diye isimlendirebileceğimiz bu özellik ile, union ve intersection type’ları bir arada kullanabiliyoruz. (union ve intersection typelara daha önceki yazılarda değinmiştim) Bu iki grubu birleştirirken, parantezler ile gruplamamız gerekiyor:

function generateArticleLink((HasTitle&HasId)|null $article): string
{
if (is_null($article)) {
return '';
}
return "{$article->getTitle()}/{$article->getId()}";
}

Burada kullandığımız (HasTitle&HasId)|null tanımlaması, DNF oluyor.

Konuyla alakalı RFC’ye buradan ulaşabilirsiniz.

Constants in Traits

Bu versiyon ile birlikte artık trait içerisinde constant tanımlamaları yapabiliyoruz:

trait Example
{
public const FOO = 'foo';
public function getFoo(): string
{
return self::FOO;
}
}

Burada en önemli husus, trait içerisinde tanımlamış olduğunuz constant değerlere, trait içinde veya dışında direkt olarak TraitAdı::SABIT şeklinde erişemiyor olmak:

trait Example
{
public const FOO = 'foo';
public function getFoo(): string
{
return Example::FOO; // Hatalı kullanım
}
}
Example::FOO; // Hatalı kullanım

Tabi ki bu değerlere tanımlanan trait’i bir class (sınıf) içerisinde kullanmaya başladıktan sonra, access type durumuna göre (public/private) classdan veya dışarıdan erişebiliriz:

class Test
{
use Example;
}
Test::FOO; // foo

Bu konu ile alakalı RFC’ye buradan ulaşabilirsiniz.

New Random Extension

Bu sürümde bizi Randomizer isimli yeni bir sınıf karşılıyor. Bu sınıfın eklenme amacı; daha önceki sürümlerde random veri üretmekte yaşanan problemlere, güvenlik sorunlarına ve performans sorunlarına daha iyi bir çözüm üretmek. Bu yeni eklenen sınıf ile birlikte farklı rastgele veri üreten motorlar (engine) kullanabiliyoruz.

Örnek vermek gerekirse; sisteminiz için production için başka bir random engine, test ve development ortamları için ise başka bir random engine kullanmak isteyebilirsiniz. Şöyle bir kullanım söz konusu olabilir:

$engine = isProduction()
? new Random\Engine\Secure()
: new Random\Engine\Mt19937(1234);

$randomizer = new Random\Randomizer($engine);
$randomizer->shuffleString('abcdefghijklmn');

Konu ile alakalı RFC’ye buradan ulaşabilirsiniz.

Redact Parameters in Back Traces

Bu özelliği kısaca şöyle özetlemek istiyorum: Bildiğiniz gibi, yazmış olduğumuz uygulamalar üzerindeki hata durumlarını genellikle logluyor ve takip ediyoruz. Loglama belki de bir uygulamanın en önemli parçalarından birini oluşturuyor. Loglama işlemi yaparken gerek sistem üzerinde belirli bir dosyada bunları tutabiliyoruz, gerekse third-party araçlar kullanarak bu log verilerini başka başka sistemlere gönderiyor ve kayıt altına alıyoruz. Bu aşamada uygulamamızda oluşan exception veya hata durumlarında back trace verilerini de loglarımıza ekliyor olabiliriz. Bu durumda kodun hata aldığı yerdeki olası sensitive verileri de log içerisinde barındırmış, belki de third-party sistemlere göndermiş oluyor. Burada sensitive bir veri söz konusu olduğu için böyle durum biraz can sıkıcı olabilir. PHP 8.2 ile birlikte gelen “Redact Parameters in Back Traces” özelliği ile istediğimiz parametreleri sensitive olarak işaretleyebiliyoruz:

function login(
string $email,
#[\SensitiveParameter] string $password
) {
// ...

throw new Exception('Error');
}

login('user@example.com', 'user-password');

Yukarıdaki örnekteki gibi kullanıcıyı login etmeyi amaçlayan ve geçersiz durumlarda bir exception throw eden bir fonksiyonumuz olduğu düşünelim. Fonksiyona dikkatli baktığımızda$password parametresinin önünde #[\SensitiveParameter] attribute’ünün kullanıldığını görüyoruz. (Attributes ile alakalı daha önceki yazılarda bilgi vermiştim) Bu attribute sayesinde ilgili parametreyi sensitive bir data olarak işaretlemiş ve olası bir durumda bu verinin gizlenmesi gerektiğini belirtiyoruz. Bu fonksiyon bir exception gönderdiğinde, şöyle bir çıktı alacağız:

Fatal error: Uncaught Exception: Error in login.php:9
Stack trace:
#0 login.php(11): login('user@example.com', Object(SensitiveParameterValue))
#1 {main}
thrown in login.php on line 9

Gördüğünüz gibi almış olduğumuz hata üzeride sensitive olan parametremizin değerini göremedik. Bu veri sensitive olarak işaretlediğimiz için gizlendi.

Konu ile alakalı RFC’ye buradan ulaşabilirsiniz.

Return type changes for `DateTime::createFromImmutable()` and `DateTimeImmutable::createFromMutable()`

Bu kritik bir değişiklik ve eğer bu metotları kullanıyorsanız, uygulamanızın çalışmasını kırabilir. Şuradan upgrading dokümanına ulaşmak mümkün.

Özetle, bahsi geçen metotlar için dönüş tiplerinde bir değişiklik yapmışlar. Önceden şu şekilde bir kullanım sağlıyordu:

DateTime::createFromImmutable(): DateTime
DateTimeImmutable::createFromMutable(): DateTimeImmutable

PHP 8.2 ile birlikte bu tanımlama şöyle değişmiş:

DateTime::createFromImmutable(): static
DateTimeImmutable::createFromMutable(): static

Hali hazırda bu metotları kullanıyorsanız, upgrade işlemi yapmadan mutlaka kodunuzu bu duruma göre düzenleyin.

Son Söz

Her ne kadar malum geyikler bitmese de, PHP gelişmeye ve daha iyi olmaya devam ediyor. Sonraki sürümler için de güzel çalışmalar yapılmaya devam ediliyor. 2022 Kasım sonuna doğru PHP 8.2 çıkmış olacak ama, şimdiden PHP 8.3 içinde çalışmalar yürütülmeye başlanmış.

Go, NodeJS, vb… gibi güçlü alternatifleri olmasına rağmen, PHP de gerek ekosistemi, gerekse aktif olarak geliştirilen ve milyonlarca kişi tarafından kullanılan tool ve frameworkleri ile birlikte hala birçok proje ve sistem için önemli bir alternatif olduğunu bizlere gösteriyor. PHP’yi sevelim ❤

Sağlıcakla ve kodla kalın.
Sevgiler.

Kaynaklar

--

--

İzni Burak Demirtaş

nam-ı diğer Buki. 👨🏻‍💻 Sr. Software Engineer @Jotform — #php #golang #javascript #reactnative — Co-Founder at HaberSistemim & MemleketApp