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