Kategorie: PHP

Jak se mi žije s PHP 8?

Tak jo, PHP 8 je tu s námi už nějakou chvíli. Přineslo spousty změn a vylepšení. Tak jsem se tedy odhodlal přepsat svůj RS::RS tak, aby si spolu tihle dva rozuměli. Při práci jsem měl radost z toho, jak krásně to šlo.

Co je v PHP 8 (pro mně) nejzajímavější?

Definice atributů třídy pouze v konstruktoru

V dobách PHP 7.x se třída s nějakými atributy deklarovala následujícím způsobem:

private PageUpdateFacade $pageUpdateFacade;
private PageSelectFacade $pageSelectFacade;
private int $parentId;

public function __construct(
    int $parentId,
    PageUpdateFacade $pageUpdateFacade,
    PageSelectFacade $pageSelectFacade
) {
    $this->pageUpdateFacade = $pageUpdateFacade;
    $this->pageSelectFacade = $pageSelectFacade;
    $this->parentId = $parentId;
}

To je samozřejmě v pořádku. Celkem přehledný a jasný kód. Pouze 13 řádků. Když se tak ale nad tím člověk zamyslí, je tu každý atribut hned na třech řádcích. No a právě to se s příchodem PHP 8 mění. Od teď je to ještě přehlednější:

public function __construct(
    public readonly int $parentId,
    public readonly PageUpdateFacade $pageUpdateFacade,
    public readonly PageSelectFacade $pageSelectFacade,
) {
}

Ano, vážně je to takhle jednoduché. Ze 13 řádků je 6, a navíc žádné opakování v kódu.

Všímavý čtenář si jistě všimne, že jsou všechny atributy deklarované jako public. To by v PHP 7.x trochu porušovalo pravidla OOP a snižovalo bezpečnost kódu. Nicméně v PHP 8.2 přibyla další novinka:

Readonly při deklaraci atributu

Když se znovu podíváš na ten konstrukktor, je za slovem "public" uvedena ještě klauzule "readonly". Ta zajistí, že i když je atribut viditelný zvenčí, nejde měnit. Dá se jen číst nebo prostě použít. Bezvadná vychytávka.

Čárka na posledním řádku

Opět tě odkážu na kód konstruktoru

public function __construct(
    public readonly int $parentId,
    public readonly PageUpdateFacade $pageUpdateFacade,
    public readonly PageSelectFacade $pageSelectFacade,
) {
}

Na řádku 4 vidíš, že posledním znakem je čárka, jako by měl následovat další řádek s atributem. To by v PHP 7 skončilo chybou. Nicméně od verze 8 už je to v pořádku. Drobnost, ale potěší.

Nové funkce

Co mě potěšilo hodně, to je pár funkcí. Čtyři z nich budu určitě používat. Jsou to:

str_contains

Tahle funkce vrací true, pokud najde v nějakém stringu jiný string. Když nenajde, vrátí false. Použití je intuitivní:

str_contains("Krabice", "ice"); // true
str_contains("Slonice", "a"); // false
 
str_contains("Ulice", "");  // true
str_contains("", "");     // true

Pokud hledáme prázdný řetězec, ten se najde vždy. Dokonce i v jiném prázdném řetězci.

str_starts_with

Test, zda nějaký řetězec začíná jiným řetězcem. Pravidlo pro prázdný řetězec je: vždy true.

str_starts_with("Krabice", "Kra"); // true
str_starts_with("Slonice", "Kra"); // false
 
str_starts_with("Ulice", "");  // true
str_starts_with("", "");     // true

str_ends_with

Asi tušíš podobnost s funkcí str_starts_with. Ano, jde o test, zda řetězec končí jiným řetězcem.

match

Tohle je opravdu paráda. Myslím, že po funkci switch s jejími cache a povinnými breaks už asi nesáhnu. Co v dobách před PHP 8 uměl switch takto:

switch ($statusCode) {
    case 200:
    case 300:
        $errorMessage = null;
        break;
    case 403:
        $errorMessage = 'forbidden';
    case 404:
        $errorMessage = 'not found';
        break;
    case 500:
        $errorMessage = 'server error';
        break;
    default:
        $errorMessage = 'unknown status code';
        break;
}

S tím si match poradí takto:

$errorMessage = match($statusCode){
    200, 300 => null,
    403 => 'forbidden',
    404 => 'not found',
    500 => 'server error',
    default => 'unknow status code',
};

No není to krása? Žádná možnost zapomenout na povinný break, žádné opakované plnění proměnné $errorMessage, sloučení dvou větví, definice default hodnoty. A počet řádků v kódu se také zmenšil.

Nullsafe operátor

Tak tohle pomůže jak k přehlednosti kódu, tak i v množství psaní. Jde o to, že můžeme vyhodnocovat, jestli není nějaká hodnota nebo výstup funkce rovno null. Všechno zařídí operátor ?->. Funguje to opět celkem intuitivně. Máme například za úkol nastavit proměnnou $phone. Hodnotu najdeme v objektu $customer. Jenže kdyby byl $customer null, nebo cokoliv v něm na cestě k phone, opět by nám to skončilo chybou. V PHP 7.x jsme museli ošetřit celou cestu takto:

$phone =  null;
  
if ($customer !== null) {
    $personalData = $customer->getPersonalData();
  
    if ($personalData !== null) {
        $phone = $personalData->phone;
    }
}

Nejprve bylo tedy nutné nastavit $phone na null. Pak následoval test, jestli $customer není také null. Kdyby totiž byl, skončilo by volání metody getPersonalData() chybou. Jesli se metoda getPersonalData() zavolat dá, ale sama vrací null, nemohli bychom si vytáhnout hodnotu phone. A tedy další test. A kdyby byla struktura objektu $customer ještě zanořenější, s každou další úrovní by musel být proveden další test.

V PHP 8 je to legrace:

$phone =  $customer?->getPersonalData()?->phone;

Všechno přehledně na jednom řádku. Jakmile se cokoliv u otazníčku vyhodnotí jako null, zastaví se další vyhodnocování a je vrácen null

Komentáře

Přidat komentář

O mně

Jmenuji se Rudolf Svátek - lektor výpočetní techniky, trochu PHP programátor a SEO konzultant na volné noze.

Adresa

Příčná 326/3
736 01 Havířov

Kontakty

Email: office@rudolfsvatek.cz
Telefon: +420 777 828 353
Skype: svatekr