PHP 8 İle Gelen Yenilikler

PHP 8 İle Gelen Yenilikler

JIT (JUST IN TIME)

Bu sürümde en fazla dikkat çeken ve merak uyandıran JIT ile başlayalım. PHP, çalışma anında (run time) yorumlanan bir dil(di). JIT ile birlikte, makine diline derlenerek yorumlanmaya başlıyor.

Bunun temel sebebi olarak; run-time yorumlamaya bağlı kalındığı sürece daha fazla performans iyileştirmesinin yapılamayacağı olarak belirtilmiş.

Bu özelliği opsiyonel olarak opcache üzerinden aktif edebileceğiz veya kapatabileceğiz. PHP5'ten PHP7'ye geçildiğinde çok yüksek bir performans farkı olduğunu görmüştük. PHP7'den PHP8'e geçtiğimiz ama JIT’i aktif etmediğimiz senaryoda sanırım böyle bir fark göremeyeceğiz.

2018 yılında Zeev Suraski, PHP 7 ile JIT’i kıyaslayan PoC gerçekleştirmiş, ciddi bir performans iyileştirmesi sunduğunu göstermişti. Ayrıca JIT sayesinde performansın 4 kattan fazla iyileşeceği belirtilmiş.

İşin daha derinini / çekirdeğini merak edenler için şöyle bir bilgi paylaşayım. Compile işlemi için önce LLVM denenmiş. Ancak performans olarak beklentilerin altında kalmış. Sonrasında DynASM — LuaJIT ile geliştirmeye başlamışlar ve 100 kata kadar daha iyi bir performans yakalamışlar. Daha fazla teknik detay merak ediyorsanız RFC sayfasını incelemenizi öneririm.

NAMED ARGUMENTS

Artık fonksiyonlara / method’lara parametreleri sırasıyla geçmek zorunda değiliz. Parametrenin adını belirterek, istediğimiz sırada kullanabiliyoruz. Kodun daha okunaklı ve anlaşılır olmasına katkısı olacağını düşünüyorum.

3 argüman alabilen round($val, $precision, $mode) fonksiyonu ile örnekleyelim. 2. sıradaki argümanı (precision) göndermeden 1. ve 3. sıradaki argümanla bu fonksiyonu çağırabileceğiz. İkinci örnekte in_array fonksiyonunda named argument kullanımını görebilirsiniz.

 
<?php

// PHP 7
round(1.49, 0, PHP_ROUND_HALF_UP);

// PHP 8 (2. SIRADAKI PARAMETREYI GONDERMEDIK)
round(val: 1.49, mode: PHP_ROUND_HALF_UP);

// PHP 7
in_array("FIFA", ["CALL OF DUTY","FIFA","PUBG"]);

// PHP 8
in_array(
  needle: "FIFA",
  haystack: ["CALL OF DUTY","FIFA","PUBG"]
);
 
 
 
 

ATTRIBUTES

PHP için yeni ama ekosistem için sıradan bir özellik gelmiş. Java’da Annotation, Python’da Decorators olarak biliniyor. C# tarafında olduğu gibi PHP’de bu özelliği Attributes olarak isimlendirmişler.

Spring Boot ile geliştirme yaparken aşina olduğumdan mı bilmiyorum ama benim en sevdiğim yeniliklerden biri oldu. Başlı başına ele alınacak bir konu olduğunda buraya inceleyebilmeniz için linkleri bırakıyorum.

https://wiki.php.net/rfc/attributes_v2
https://wiki.php.net/rfc/attribute_amendments
https://wiki.php.net/rfc/shorter_attribute_syntax
https://wiki.php.net/rfc/shorter_attribute_syntax_change

NULLSAFE OPERATOR

En sevdiğim özelliklerden biri. Sürekli “if” yazıp null check yapıyorduk. Artık bunu yapmak için soru işareti operatörünü kullanmamız yeterli olacak. Aslında Swift, C#, JavaScript gibi dillerde zaten bu özellik bulunuyordu. PHP geç kaldı bile diyebiliriz. Darısı Java’nın başına! :)  

<?php

// PHP 7
if($user !== null) {
  $socialAccounts = $user->getSocialAccounts();
 
  if($socialAccounts->getFacebook() !== null) {
    $facebookAccount = $socialAccounts->getFacebook();
  }
 
}

// PHP 8
$facebookAccount = $user?->getSocialAccounts()?->getFacebook();

 

MATCH EXPRESSION

Artık switch ile çok benzer başka bir eşleştirme / karşılaştırma alternatifimiz var; Match.

Kullanımı oldukça basit.  

<?php

// PHP 7 (Switch)
switch ($status) {
  case 0: return 'Disable';
  case 1: return 'Enable';
}

// PHP 8
match($status) {
  0 => "Disable",
  1 => "Enable",
};
 

Switch varken böyle bir şeye gerçekten ihtiyaç var mıydı? Bunun başlıca sebepleri şöyle açıklanmış.

  1. Switch’te type safe karşılaştırma yapılmıyor. Bu bazen şaşırtıcı sonuçlara sebep olabiliyor.
  2. Switch’te koşul sağlandığında “break” yazmayı unuttuğunuzda, diğer koşul için kontrol yapılmaya devam ediliyor.

Diğer detaylar için match expression sayfasını inceleyebilirsiniz.

CONSTRUCTOR PROPERTY PROMOTION

PHP7'de constructor’da objeye değer almak için;
1. Property olarak tanımla
2. Constructor parametresi olarak tanımla
3. Constructor içerisinde alınan parametreyi property’e tanımla
adımlarını takip ediyorduk.

Artık bunu çok daha kısa bir yolla yapabileceğiz. Constructor’a arguman belirtmemiz yeterli olacak. Hemen bir örnek ile inceleyelim.  

<?php

// PHP 7
Class Position
{
    protected int $top;
    protected int $bottom;
    protected int $left;
    protected int $right;
   
    public function __construct(
        int $top    = 0,
        int $bottom = 0,
        int $left   = 0,
        int $right  = 0
    ) {
       $this->top = $top;
       $this->bottom = $bottom;
       $this->left = $left;
       $this->right = $right;
    }
}

// PHP 8
Class Position
{  
    public function __construct(
        protected int $top    = 0,
        protected int $bottom = 0,
        protected int $left   = 0,
        protected int $right  = 0
    ) {
      // :)
    }
}
 

UNION TYPES

PHP 7 ile birlikte type declaration / type safety kullanmaya başlamıştık. Artık bir parametrenin veya dönüş türünün birden fazla türe sahip olabilmesi sağlanıyor.

Daha önce hem integer hem de null olabilecek noktaları ?int gibi tanımlayabiliyorduk. Artık; “hem Integer hem de Float olabilir” gibi bir tanım yapabiliyoruz.  

<?php

class Game {
  private int|float $score;
 
  public function setScore(int|float $score): void {
    $this->score = $score;
  }
 
  public function getScore(): int|float {
    return $this->score;
  }
}

 

Ayrıca artık mixed type bulunuyor. Özellikle legacy projelerde çok fazla dönüş tipi bulunan kodları refactor ederken kullanılabilir.

Ancak bir yandan da yeniden karmaşıklığa yol açabilir. Hem type safety olma yolunda ilerlerken hem de “mixed” gibi bir türün implemente edilmesi çok ilginç olmuş.

NON CAPTURING CATCHES

Artık bir exception yakaladığımızda bunu bir değişkene atamak zorunda değiliz. Sadece Exception objesini kullanacağımız zaman değişkene atayabiliriz.  

<?php

// PHP 7
try {
    User::get($userId);
} catch (UserNotFound $e) {
    return "User Not Found!";
}

// PHP 8
try {
    User::get($userId);
} catch (UserNotFound) { // not declared $e
    return "User Not Found!";
}
 

STRING MATCH FUNCTIONS

Artık 3 adet yeni fonksiyona sahibiz. Önceden Symfony, Laravel gibi framework’lerin helper’ları ile bu işlemleri yapıyorduk. Keşke core’a eklenmesi için bu kadar yıl beklemek zorunda kalmasaydık.

str_starts_with: string’in belirttiğimiz değerle başlayıp başlamadığını kontrol eder, boolean değer döndüdür.

str_ends_with: string’in belirttiğimiz değerle bitip bitmediğini kontrol eder, boolean değer döndüdür.

str_contains: string’in içerisinde belirttiğimiz değerin olup olmadığını kontrol eder, boolean değer döndüdür.  

<?php

str_starts_with("Lorem Ipsum", "Lorem"); // true
str_starts_with("Lorem Ipsum", "Ipsum"); // false

str_ends_with("Lorem Ipsum", "Ipsum"); // true
str_ends_with("Lorem Ipsum", "Lorem"); // false

str_contains("Lorem Ipsum", "rem"); // true
str_contains("Lorem Ipsum", "sit amet"); // false
 

STATIC RETURN TYPE

Artık static tipini geriye döndürerek kullanabileceğiz.  

<?php

class User {
    public function create($user): static {
        return new static($user);
    }
}
 
ÖNEMLİ *

Bu versiyonda geriye yönelik uyumluluk anlamında problem oluşturabilecek değişiklikler bulunuyor. PHP 7.4'te doğru çalışan bir business logic, PHP8 ile birlikte farklı bir davranış göstermeye başlayabilir.

Özellikle “string to number comparisons” başlığını mutlaka incelemenizi ve yeni davranışa göre kodunuzu refactor etmenizi öneririm.

 

Kaynak

Yorumunuzu Ekleyin


Yükleniyor...
Yükleniyor...