Dikkat: PHP 8 büyük bir güncelleme ve önemli değişiklikler içeriyor. Sisteminizi güncellemeden önce yapabileceğiniz en iyi şey yükseltme belgesindeki son değişikliklerin tam listesine bakmanız olucaktır.
PHP 8'deki Yenilikler
Union Types (Birleşik Tipler)
Bildiğiniz üzere PHP’nin önceki versiyonlarında bir değişkenin tipini belirleyebiliyorduk. Örneğin insan(string $isim, int $cinsiyet)
fonksiyonu kişinin cinsiyetini döndürüyor ise function insan(string $isim, int $cinsiyet): stdClass
gibi.
Artık birden fazla değişken tipi belirleyebiliyoruz. İnsan fonksiyonu \Dunya\Canli\Insan
sınıfını ve $cinsiyet
değişkeni \Dunya\Canli\Erkek
veya \Dunya\Canli\Kadin
sınıfınıda olabilir.
Peki bunu nasıl kullanabiliriz? Eskiden tipleri sadece string
olarak belirtiyorsak artık string|int|boolean
gibi uzatabiliyoruz. Örneğin;
function insan(?string $isim, \Dunya\Canli\Erkek|\Dunya\Canli\Kadin|null $cinsiyet = null): \Dunya\Canli\Insan
{
return Insan::bilgiler($isim, $cinsiyet);
}$isim = "nur";
$cinsiyet = new \Dunya\Canli\Kadin;
print_r(insan($isim, $cinsiyet));
JIT (Just In Time / Tam Zamanında)
Açılımı “Just In Time” Türkçeye “Tam Zamanında” olarak çevirilen yeni PHP derleyicisi HTTP istekleri öncelikli olmasada önemli performans iyileştirmeleri vaat ediyor. Detaylı bir makaleyi stitcher.io adresinden bulabilirsiniz.
Nullsafe İşleci
Bu özelliği anlamanız için bir seneryo oluşturalım. Örneğin $insanlar
değişkeniniz var ve insanlar whatsapp
değişkenine sahipler fakat birinde bu değişken eksik ve bu altdaki kod bloğunda olduğu bir kod hata veriyor.
foreach($insanlar as $insan) {
merhaba($insan->whatsapp);
}
Bu hatayı basit olarakisset($insan->whatsapp) ? $insan->whatsapp : null
şeklinde giderebiliriz ancak nullsafe işleci sayesinde bunu $insan?->whatsapp
olarak düzeltebiliyoruz. Bu yeniliği ilerleyen zamanlarda sık sık göreceğiz frameworkler ve yazım standartlarda kullanılmaya başlayacağı şüphesiz.
Adlandırılmış Değişkenler (Named arguments)
class Insan {
public function __construct(
public string $isim,
public int $yas,
) {}
}
Yukardaki kod PHP dışında bir dile ait gibi görünebilir, evet artık sadece fonksiyon oluşturarak bir sınıfın içinde public bir değişken oluşturabiliyoruz. Ayrıca fonksiyonu çağırırken değişken isimlerini belirtebilirsiniz örneğin:
$insan = new Insan(
isim: "İsa",
yas: 19
);
Öznitellikler (Attributes)
Öznitellikler, docblock’ları ayrıştırmak zorunda kalmadan sınıflara meta veri eklemenin bir yolunu sunar. Kısa bir örnekle:
// OrnekAttribute.php
#[Attribute]
class OrnekAttribute {
public $value; public function __construct($value) {
$this->value = $value;
}
}
Yukarıdaki kod bloğu ile bir öznitelik sınıfı oluşturmuş olduk şimdi aşağıdaki kod bloğundaki örnekteki gibi kullanıyoruz.
// Sini.php
$[OrnekAttribute]
class Sinif {
#[OrnekAttribute]
public int $sinif = 12; #[OrnekAttribute]
public string $sute = 'B'; #[OrnekAttribute]
public function ogrenciEkle(#[OrnekAttribute] $ogrenci) {}
}
Match İfadesi
Buna switch’in kısayolu diyebiliriz. match, değerleri döndürebilir, break ifadeleri gerektirmez, koşulları birleştirebilir, katı tür karşılaştırmaları kullanır ve herhangi bir tür zorlaması yapmaz. Kullanımı altdaki kod bloğundaki gibidir.
$kod = 200;
$cevap = match($kod) {
200, 300 => null,
404 => 'bulunamadı',
500 => 'sunucu hatası',
default => 'bilinmeyen durum',
};
“static” Dönüş Türü
Artık sınıflarınızın içindeki fonksyonlarıdan static bir veri döndürebilirsiniz. Örneğin:
class Kullanici {
public function olustur($degerler): static {
$kullanici = clone $this;
$kullanici->olustur($degerler);
return $kullanici;
}
}
“mixed” Dönüş Türü
Daha önceden türleri birden fazla belirleyemiyorduk, PHP 8 ile birden fazla tür ile birlikte mixed
türüde geldi. Bu türün anlamı ise değerin listedeki tiplerden herhangi biri olabiliceği anlamına geliyor.
- array
- bool
- callable
- int
- float
- null
- object
- resource
- string
Örnek:
function kullaniciBul(): mixed {}
Not: mixed değeri nullable olamaz
Throw ifadesi
Artık hataları kısaltılmış ifadeler ile kullanabiliyoruz. Örneğin;
$resim = $resimler[0] ?? throw new Hatalar\ResimYok();
Özel fonksiyonlar için güncelleme
Öncede, PHP aynı miras denetimlerini public, private ve protected methodlarına uygulardı. Başka bir deyişle: private methodlar, protected ve public methodlar ile aynı şekilde çalışıyordu. Private methodlara alt classlar tarafından erişilemiyordu ve bu mantıklı değildi.
Bu davranış değiştirildi, böylece bu devralma kontrolleri artık private methodlarda gerçekleştirilmiyor. Dahası, final private function kullanılması da mantıklı değildi, bu nedenle bunu yapmak artık bir uyarı tetkliyor:
Warning: Private methods cannot be final as they are never overridden by other classes
Objelerde ::class
Bu yeni özellik, objelerde ::class
kullanımına izin veriyor.
$ornek = new Ornek();
var_dump($ornek::class);
Hataları almadan hata yakalamak
Önceden try/catch kullanımında hatayı almak zorundaydık artık PHP 8'de hatayı bir değişkene atamak zorunda değiliz. Örneğin önceden aşağıdaki gibi bir kod kullanmak zorundayken;
try {
// hata
} catch (Exception $exception) {
Log::error("Hata oluştu");
}
Artık burada $exception
değişkenini atamak zorunda değiliz:
try {
// hata
} catch (Exception) {
Log::error("Hata oluştu");
}
Not: Her zaman türü belirtmeniz gerektiğini, boş bir exception hakkına sahip olamayacağınızı unutmayın. Tüm istisnaları ve hataları yakalamak istiyorsanız, yakalama türü olarak Throwable’ı kullanabilirsiniz.
Parametre listesinde son virgül
Bildiğiniz üzere Array’larda zaten sona virgül eklenebiliyordu, PHP 8'de artık bir fonksiyon oluştururken parametrelerin sonunada virgül ekleyebileceğiz. Yani aşağıdaki kod hata vermeyecektir.
public function(string $ilkParametre, int $ikinciParametre,) {
// ...
}
Interface kullanarak DateTime objesi oluşturmak
Artık DateTimeInterface kullanarak DateTime objesi oluşturabiliyoruz. Bunun için iki yeni fonksiyon eklendi: DateTime::createFromInterface()
ve DatetimeImmutable::createFromInterface()
DateTime::createFromInterface(DateTimeInterface $interface); DateTimeImmutable::createFromInterface(DateTimeInterface $interface);
Stringable
Artık Stringable interface’ini kullanabilirsiniz. Örnek kullanımı:
class Ornek implements \Stringable {
public function __toString(): string {
return "Merhaba Dünya!";
}
}function ornekFonksyion(string|Stringable $yazi) {
var_dump($yazi);
}ornekFonksiyon(new Ornek);
ornekFonksiyon("Merhaba Dünya!");
str_contains
Önceden bir string içeriğinde aramak yapmak için aşağıdaki yöntem kullanılıyordu:
if (strpos("merhaba dünya", "merhaba") !== false) {}
Artık PHP 8'de bunu kullanabiliyoruz:
if (str_contains("merhaba dünya", "merhaba")) {}
str_starts_with ve str_ends_with fonksiyonları
Sonunda bu iki fonksiyon PHP’ye eklendi. Kullanımları:
str_starts_with('Merhaba Dünya', 'Merhaba'); // true
str_ends_with('Merhaba Dünya', 'Dünya'); // true
fdiv() fonksiyonu
Yeni eklenen fdiv()
fonksiyonu aslında fmod()
ve intdiv()
fonksiyonlarının bir benzeri. İşlevi 0'a bölmeye izin verir. Hata yerine duruma bağlı olarak INF
, -INF
veya NAN
alırsınız.
get_debug_type() fonksiyonu
get_debug_type()
fonksiyonu değişkenin tipini döndürür.
Örneğin, getype()
ile \Ornek
sınıfındaki bir değişkeni kontrol ettiğinizde object döndüğünü görüceksiniz fakat get_debug_type()
fonksiyonu class’ı döndürücektir.
get_debug_type()
ve gettype()
fonksiyonları arasındaki farkın tüm listesini buradan bulabilirsiniz.
get_resource_id() fonksiyonu
Resource’lar, PHP’de harici resourcelara atıfta bulunan özel değişkenlerdir. Örnek olarak MySQL bağlantılarını veya dosyaları verebiliriz.
Bu resourceların her birine bir id atanır, ancak daha önce bu resourceları bilmenin tek yolu resource’u int’ye çevirmekti.
$resourceId = (int) $resource;
PHP 8'de bu fonksiyon ile bu işlem daha açık ve tür açısından daha güvenli hale getirildi.
$resourceId = get_resource_id($resource);
Traitlerde değişken tipleri
trait Ornek {
abtract public function test(int $degisken): int;
}class Kullanim {
use Ornek; public function test($degisken) {
return $degisken;
}
}
PHP 8'de değişkenlerin tiplerini belirtmemiz gerekmekte yani bu kod aşağıdaki gibi olmalı.
class Kullanim {
use Ornek; public function test(int $degisken): int {
return $degisken;
}
}
Dahili fonksiyonlar için tür açıklamaları
Birçok insan tüm dahili fonksiyonlara açıklama yazmak için bir araya geldi. Uzun zamandır devam eden bu işlem sonunda tamamlandı ve PHP’nin yeni versiyonunda dahili fonksiyonların ve methodların detaylı bir dökümasyonu bulunmakta.
ext-json her zaman kullanılabilir
Önceden PHP’yi JSON uzantısı etkinleştirilmeden derlemek mümkündü, bu artık mümkün değil. JSON çok yaygın olarak kullanıldığından, geliştiriciler, uzantının önce var olduğundan emin olmak yerine, her zaman orada olduğuna güvenebilirler.
Tutarlı tür hataları
PHP’deki kullanıcı tanımlı işlevler zaten TypeError’ı vericektir, ancak dahili fonksiyonlar ve methodlar bunu yapmıyordu, bunun yerine uyarılar veriyor ve boş veri döndürüyorlardı. PHP 8'den itibaren dahili fonksiyon ve methodların davranışı tutarlı hale getirildi.
Uyarılar yeniden sınıflandırıldı
Daha önce yalnızca uyarıları veya bildirimleri tetikleyen birçok hata, doğrudan hatalara dönüştürüldü. Aşağıdaki uyarılar değiştirildi.
- Undefined variable: notice yerine
Error
- Undefined array index: notice yerine warning
- Division by zero: warning yerine
DivisionByZeroError
- Attempt to increment/decrement property ‘%s’ of non-object: warning yerine
Error
- Attempt to modify property ‘%s’ of non-object: warning yerine
Error
- Attempt to assign property ‘%s’ of non-object: warning yerine
Error
- Creating default object from empty value: warning yerine
Error
- Trying to get property ‘%s’ of non-object: notice yerine warning
- Undefined property: %s::$%s: notice yerine warning
- Cannot add element to the array as the next element is already occupied: warning yerine
Error
- Cannot unset offset in a non-array variable: warning yerine
Error
- Cannot use a scalar value as an array: warning yerine
Error
- Only arrays and
Traversables
can be unpacked: warning yerineTypeError
- Invalid argument supplied for foreach(): warning yerine
TypeError
- Illegal offset type: warning yerine
TypeError
- Illegal offset type in isset or empty: warning yerine
TypeError
- Illegal offset type in unset: warning yerine
TypeError
- Array to string conversion: notice yerine warning
- Resource ID#%d used as offset, casting to integer (%d): notice yerine warning
- String offset cast occurred: notice yerine warning
- Uninitialized string offset: %d: notice yerine warning
- Cannot assign an empty string to a string offset: warning yerine
Error
- Supplied resource is not a valid stream resource: warning yerine
TypeError
@ operatorü artık önemli hataları susturmuyor
Bu değişikliğin PHP 8'den önce gizlenmiş hataları ortaya çıkarması mümkün. Production modundaki sunucularınızda display_errors=off
ayarını yaptığınızdan emin olun!
Varsayılan hata seviyesi
E_NOTICE
ve E_DEPRECATED
dışında her şey yerine artık E_ALL
. Bu muhtemelen PHP 8'den önce mevcut olsa da, daha önce yok sayılmış bir çok hatanın ortaya çıkabileceği anlamına geliyor.
Varsayılan PDO hata modu
RFC’den: “PDO için geçerli varsayılan hata modu sessizdir. Bir SQL hatası olduğunda, geliştirici kendi hata işlemesini uygulamadıkça hiçbir hata veya uyarı verilemeyeceği ve hiçbir istisna atılmayacağı anlamına gelir.”
RFC, varsayılan hatayı değiştirerek PHP 8'de PDO::ERRMODE_EXCEPTION
olarak değişirdi.
Birleştirme önceliği
Böyle bir şey yazarsanız:
echo "örnek: " . $x + $y;
PHP önceden bunu altdaki gibi derleyecekti
echo ("örnek: " . $x) + $y;
Fakat PHP 8'de işlem önceliği değiştirildi ve bu işlem aşağdaki gibi çalıştırılıyor.
echo "örnek: " . ($x + $y);
Aritmetik ve bitsel operatörler için daha katı tip kontrolleri
PHP 8'den önce dizilere, kaynaklara veya nesnelere aritmetik veya bitsel operatörler uygulamak mümkündü. Bu artık mümkün değil ve bir TypeError atacak:
[] % [42];
$object + 4;
Namespace’li isimler artık tek bir belirteç
PHP, bir namespace’in her bir parçasını bir dizi belirteç olarak yorumlamak için kullanılırdı. Bu davranış değiştirildi ve isimler artık namespacelerde kullanılabilir.
string ve number karşılaştırmaları
PHP’de 0 == ‘test’
ifadesinin true
olarak döndüğü garip bir hata düzeltildi.
Kararlı sıralama
PHP 8'den önce sıralama algoritmaları kararsızdı. Bu, eşit değerlerin sırasının garanti edilemediği anlamına geliyor. PHP 8'de tüm sıralama işlevlerinin davranışını geliştirildi.
Uyumsuz methodlar için önemli hata düzeltmesi
RFC’den: “Uyumsuz yöntem imzalarından kaynaklanan devralma hataları, şu anda hatanın nedenine ve devralma hiyerarşisine bağlı olarak önemli bir hata veya bir uyarı verir.”