Co se dozvíte v článku
Co je nového
Stejně jako minulé řady, přichází s PHP 8 lepší výkon, tentokrát v podobě JIT (just-in-time) kompilace. Některé benchmarky ukazují až trojnásobný výkon oproti PHP 7.4, u některých dlouho běžících aplikací je výkon až dvojnásobný.
Z novinek můžeme zmínit například:
- nové interní funkce, které známe z mnoha frameworků –
str_contains()
,str_starts_with()
astr_ends_with()
či interfaceStringable
, - striktnější kontrolu typů při bitových a aritmetichých operacích (viz RFC),
- validaci abstraktních metod u traitů (viz RFC),
- změny v chybách,
- změny v dědičnosti privátních metod (viz RFC),
- operátor
@
již nemá vliv na fatální chyby, mixed
typ,static
jako návratový typ (viz RFC).
Na některé novinky se nyní podíváme trochu blíže.
Pojmenované agrumenty
Pojmenované argumenty (named aguments) známe například z Pythonu. Moderní IDE sice argumenty funkcí napovídají, ale nový zápis je jistě přehlednější.
<?php // PHP 7 htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); // PHP 8 htmlspecialchars($string, double_encode: false);
Atributy
Místo anotací podle standardu PHPDoc, můžeme nyní použít nativní atributy. Výhodou může být například jejich podpora v reflection API.
<?php // PHP 7 class PostsController { /** * @Route("/api/posts/{id}", methods={"GET"}) */ public function get($id) { /* ... */ } } // PHP 8 class PostsController { #[Route("/api/posts/{id}", methods: ["GET"])] public function get($id) { /* ... */ } }
<?php class PostsController { #[Route("/api/posts/{id}", methods: ["GET"])] public function get($id) { /* ... */ } } $reflectionClass = new ReflectionMethod(PostsController::class, 'get'); $attributes = $reflectionClass->getAttributes(); var_dump($attributes[0]->getName()); var_dump($attributes[0]->getArguments());
string(5) "Route" array(2) { [0]=> string(15) "/api/posts/{id}" ["methods"]=> array(1) { [0]=> string(3) "GET" } }
Definice atributů třídy v konstruktoru
Díky constructor property promotion také napíšete o kousek kódu méně.
<?php // PHP 7 class Point { public float $x; public float $y; public float $z; public function __construct( float $x = 0.0, float $y = 0.0, float $z = 0.0, ) { $this->x = $x; $this->y = $y; $this->z = $z; } } // PHP 8 class Point { public function __construct( public float $x = 0.0, public float $y = 0.0, public float $z = 0.0, ) {} }
Union Types
Namísto současného použití PHPDoc anotací pro případ, že proměnná můžeme různých datových typů, můžeme typy kombinovat při deklaraci např. atributu třídy. Tyto deklarace jsou pak při běhu skriptu validovány.
<?php // PHP 7 class Number { /** @var int|float */ private $number; /** * @param float|int $number */ public function __construct($number) { $this->number = $number; } } new Number('NaN'); // Toto je v pořádku // PHP 8 class Number { public function __construct( private int|float $number ) {} } new Number('NaN'); // Vyvolá výjimku TypeError
Výrazy s match
S PHP 8 přichází nové klíčové slovo match
, které má jistou podobnost se switch
blokem. Můžeme jej charakterizovat takto:
match
je výraz, čili jeho výsledek můžeme uložit do proměnné nebo jej může vracet funkce,match
pracuje pouze s jednořádkovými výrazy, nemá žádnou obdobu probreak
,match
porovnává striktně.
<?php // PHP 7 switch (8.0) { case '8.0': $result = "Oh no!"; break; case 8.0: $result = "This is what I expected"; break; } echo $result; // Oh no! // PHP 8 echo match (8.0) { '8.0' => "Oh no!", 8.0 => "This is what I expected", }; // This is what I expected
Nullsafe operátor
Kontrola, zda je proměnná null
, zvláště pokud se několikrát opakuje, dělá často kód hůře čitelný. Nullsafe operátor zde jistě mnohé zpřehlední.
<?php // PHP 7 $country = null; if ($session !== null) { $user = $session->user; if ($user !== null) { $address = $user->getAddress(); if ($address !== null) { $country = $address->country; } } } // PHP 8 $country = $session?->user?->getAddress()?->country;
Změny v interních funkcích
Dosud volání interní funkce s chybným typem argumentu vyvolalo pouze chybu typu Warning
, nyní je ve většině případů dochází k vyvolání příslušných výjimek, které korespondují s typem chyby.
<?php // PHP 7 strlen([]); // Warning: strlen() expects parameter 1 to be string, array given array_chunk([], -1); // Warning: array_chunk(): Size parameter expected to be greater than 0 // PHP 8 strlen([]); // TypeError: strlen(): Argument #1 ($str) must be of type string, array given array_chunk([], -1); // ValueError: array_chunk(): Argument #2 ($length) must be greater than 0
Zpětná kompatibilita
- změna při porovnávání řetězců a čísel
Výraz | Dříve | Nyní |
---|---|---|
0 == "0" |
true |
true |
0 == "0.0" |
true |
true |
0 == "foo" |
true |
false |
0 == "" |
true |
false |
42 == " 42" |
true |
true |
42 == "42foo" |
true |
false |
match
je klíčové slovo,- metoda, která má stejný název jako třída již není konstruktor, je třeba používat výhradně
__construct()
, - byla odstraněna možnost volat staticky metody, které nejsou statické, což je zohledněno i v chování funkce
is_callable()
, assert()
nyní vyvolává výjimku, toto lze změnit pomocí ini direktivyassert.exception=0
,- bylo odstraněno přetypování
(real)
a(unset)
, - byla odstraněna ini direktiva
track_errors
, - již nelze definovat case-insensitive konstanty,
- funkci
__autoload()
již nelze použít k autoloadingu tříd, náhrada jespl_autoload_register()
, - z funkcí pro obsluhu chyb byl odstraněn argument
errcontext
, - byly odstraněny funkce
create_function()
aeach()
, - funkci
array_key_exists()
již nelze použít pro objekty, - výchozí úroveň pro
error_reporting
je nyníE_ALL
, - ini direktiva
display_startup_errors
je ve výchozím stavu povolená, - použití
parent
ve třídě, která není potomkem žádné třídy nyní vyvolá fatální chybu, #[
již není bráno jako začátek komentáře,- desetinná čísla se budou vypisovat nezávisle na locales
<?php // PHP 7 setlocale(LC_ALL, "cs_CZ"); $f = 3.14; echo $f; // 3,14 // PHP 8 setlocale(LC_ALL, "cs_CZ"); $f = 3.14; echo $f; // 3.14
- byla odstraněna možnost přistupovat k prvkům pole pomocí složených závorek.
Frameworky a redakční systémy
Podíváme-li se do .travis.yml
nebo composer.json
velkých PHP frameworků jako jsou Symfony, Laravel, Yii nebo naše české Nette, všechny už s novým PHP počítají.
U WordPressu a Drupalu to také vypadá slibně, i poslední vydání Joomly říká, že je na PHP 8 připravené.
Instalace
Pokud chcete nové PHP začít používat, cesta je celkem snadná. Chcete-li si novinky jen vyzkoušet, jsou pro vás k dispozici třeba aktuální image pro Docker. Samozřejmě můžete zvolit i klasické balíčky, pokud používáte Debian či Ubuntu, Ondřej Surý spravuje repozitáře pro Debian i PPA pro Ubuntu, v nichž je již nové PHP k dispozici. Pro CentOS můžete použít Remi's RMP Repository, kde je PHP 8 již také k dispozici.
Novinky nejen pro programátory
Všechny novinky v PHP 8 najdete samozřejmě na stránkách PHP. Lepší výkon určitě potěší všechny a novinky v jazyku udělají jistě radost programátorům. Je třeba říci, že v době psaní článku není ještě kompletní oficiální dokumentace, např. chybí novinky v reflection API, proto je zde odkazováno především na RFC. Na závěr nezbývá než popřát co nejméně problémů při aktualizaci.