Finální verzi můžeme očekávat v listopadu nebo začátkem prosince. Stejně jako u PHP 7.0 není stanovené přesné datum vydání, ale finální verze vyjde, až bude dostatečně stabilní.
S testováním můžete začít snadno – už jsou k dispozici i buildy pro Windows a podpora ve stabilní verzi PHPStormu (stačí přepnout verzi v Settings – Languages & Frameworks – PHP). Pokud chcete porovnat chování se staršími verzemi PHP, tak doporučuji 3v4l.org (neboli php.wtf).
Prošel jsem pro vás novinky implementované v 7.1, prostudoval jsem RFC, vybral ty nejzajímavější a shrnul je i s příklady. Spoustu změn se nese v duchu zvyšování konzistence jazyka a omezování možností střelit se do nohy, u některých zrušených věcí jsem naštěstí ani nevěděl, že to je možné. Z provedených změn je vidět snahu o silnou zpětnou kompatibilitu a případná nekompatibilita je opodstatněná. Upgrade z 7.0 by tedy měl být relativně snadný.
V manuálu už přibyla sekce o upgrade na 7.1, takže si o potřebných změnách můžete přečíst i tam.
Nullable types
V PHP 7.0 přibyla možnost definovat typy parametrů funkcí a jejich návratových hodnot. Nicméně nebylo možné místo parametru s určeným typem předat null
. Obdobně nešlo vrátit null
z funkce s definovaným návratovým typem:
<?php
function foo(string $foo): string
{
return $foo;
}
foo('a'); // OK
foo(null); // TypeError: Argument 1 passed to foo() must be of the type string, null given
Obejít to šlo odebráním definice typů, případně u parametrů pomocí definice: string $foo = null
– nicméně v tu chvíli nejde jen o nullable parametr, ale zároveň je $foo
také nepovinný.
V PHP 7.1 přibyla možnost pomocí ?
označit nullable parametry a návratové hodnoty, takže můžeme bezpečně odlišit nepovinný a nullable parametr:
<?php // https://3v4l.org/mO6vd
function bar(?string $bar): ?string
{
return $bar;
}
var_dump(bar("a")); // string(1) "a"
var_dump(bar(null)); // NULL
var_dump(bar()); // Uncaught ArgumentCountError: Too few arguments to function bar()
Void return type
Od PHP 7.0 bylo možné definovat návratový typ funkce, ale nebylo možné vyžadovat nevrácení žádné hodnoty (což může být užitečné pro prevenci chyb). Teď je to možné pomocí void
:
<?php
function shouldReturnNothing(): void
{
return 1; // Fatal error: A void function must not return a value
}
V takové funkci musíme return
vynechat úplně nebo ho zavolat bez hodnoty: return;
. Vrácení null
pomocí return null;
také není platné.
Chybějící parametr uživatelsky definované funkce vyhodí Error
Pokud jste dříve zavolali funkci s chybějícími parametry, tak se provedla bez nich a zahlásila warning. Nově chybějící parametr funkce vyhodí ArgumentCountError
a funkce se vůbec neprovede.
Zdůrazňují, že se to netýká přímo funkcí v PHP, ale jen těch uživatelsky definovaných – substr();
způsobí stále jen warning.
<?php // https://3v4l.org/F9thD
function test($param)
{
var_dump($param);
}
test(); // Uncaught ArgumentCountError: Too few arguments to function test(), 0 passed and exactly 1 expected
Aritmetické operace s neplatnými stringy vrací warning či notice
V PHP <7.1 bylo možné sčítat jablka s hruškami bez warningů nebo notice:
<?php
var_dump('1' + '1'); // int(2)
var_dump('10 apples' + '5 pears'); // int(15)
var_dump('two apples' + '5 pears'); // int(5)
Pokud v PHP 7.1 použijeme aritmetickou operaci na string, který nelze převést na číslo (např. 'two apples'
) dostaneme Warning: A non-numeric value encountered in %s on line %d
. Pro stringy, ze kterých jde získat číslo ('10 apples'
) je připravena Notice: A non well formed numeric value encountered in %s on line %d
. Řetězec obsahující číslo ('10'
) se bere jako platný a notice nezpůsobí.
Definice viditelnosti konstant
Nově je možné konstanty označit jako private
nebo protected
. To přijde vhod, pokud chcete konstantu použít jen uvnitř třídy a nechcete, aby na ní někdo závisel v kódu mimo třídu.
<?php
class Token
{
const PUBLIC_CONST = 0; // = public const
public const PUBLIC_CONST_TWO = 0; // = const
protected const PROTECTED_CONST = 0;
private const PRIVATE_CONST = 0;
}
Chytání více typů výjimek v jednom catch
Pokud jsme v PHP <7.1 chtěli dva typy výjimek ošetřit stejným způsobem, bylo potřeba kód zkopírovat nebo vytvořit společnou metodu:
<?php
try {
// Some code...
} catch (ExceptionType1 $e) {
// Code to handle the exception
} catch (ExceptionType2 $e) {
// Same code to handle the exception
} catch (Exception $e) {
// ...
}
Nově je možné chytit více typů najednou:
<?php
try {
// Some code...
} catch (ExceptionType1 | ExceptionType2 $e) {
// Code to handle the exception
} catch (\Exception $e) {
// ...
}
Nový typ iterable
Při definici typehintu pro kolekci jste se museli rozhodnout, jestli použijete array
a nebude možné tam předat Traversable
nebo naopak. Obejít to šlo vynecháním typehintu a kontrolou až v kódu.
Teď už to není potřeba a můžete použít typ iterable
:
<?php
function foo(iterable $iterable)
{
foreach ($iterable as $value) {
// ...
}
}
Zároveň přibyla funkce (bool) is_iterable()
.
Negativní offsety pro stringové funkce
Některé funkce pro práci se stringy (například substr()
) umožňovaly používat negativní offsety:
<?php
substr("abcdef", -1); // "f"
Od 7.1 je možné negativní offsety používat také u funkcí: strpos()
, stripos()
, substr_count()
, iconv_strpos()
, mb_strpos()
(a několik dalších, viz RFC)
$this
se vždy bude chovat očekávaným způsobem
Tipuji, že jste nevěděli, a snad díky tomu ani nepoužívali možnost přiřadit do $this
jinou hodnotu (netuším, proč by to někdo dělal). V rámci zvyšování konzistence a odebírání historických haluzí už to naštěstí v 7.1 nepůjde.
<?php // https://3v4l.org/ZcMVY
$a = 'this';
$$a = 42;
var_dump($this); // na < 7.1 vypíše 42, na 7.1+ Fatal Error
<?php // https://3v4l.org/cAJGi
class C
{
function foo()
{
$a =& $this;
$a = 42;
var_dump($this); // na < 7.1 vypíše 42, na 7.1+ očekávaný dump $this
}
}
$x = new C();
$x->foo();
Session ID už není hashované
Bezpečně vygenerované ID (pomocí random_bytes()
přidaného v 7.0) už není potřeba hashovat, takže byly odebrány související volby v php.ini. Naopak přibyla možnost nastavení délky session id pomocí session.sid_length
. V php.ini
distribuovaném s PHP je nastaveno na 26 kvůli zpětné kompatibilitě, ale výchozí hodnota přímo v PHP je 32.
Doporučuji tedy ověřit, že sloupec (resp. místo, kam ukládáte session ID) zvládne 32 znaků, případně do php.ini
přidat session.sid_length = 26
Zkrácená syntaxe pro array destructuring
Je možné použít kratší zápis pro přiřazení pole do jednotlivých proměnných:
<?php
list($a, $b, $c) = array(1, 2, 3); // původně
[$a, $b, $c] = [1, 2, 3]; // nově také takto
Trošku odbočím, troufám si tvrdit, že použití list()
signalizuje code-smell a ve většině případů by mělo jít nahradit pomocí result objectu (tzn. metoda nebude vracet asociativní pole, ale immutable objekt). Pokud list()
používáte, zkuste se zamyslet, jestli místo přechodu na novou syntaxi nebude vhodnější upravit kód a rovnou vracet objekt. Pokud máte příklad, kde použití list()
dává smysl a neznepřehledňuje kód, tak budu rád, pokud se o něj podělíte v komentářích.
Drobnosti, které nepotřebují vlastní kapitolu
- Nová metoda pro převod callable na Closure:
Closure::fromCallable()
- Použití
eval
vmb_ereg_replace
je deprecated (zpreg_replace
bylo odebráno už v PHP 7.0) - Mcrypt je deprecated (a v další verzi bude odebrán) – je to od roku 2007 nepodporovaná knihovna
- Změny kolem generování náhodných čísel:
mt_rand()
bude používat jiný algoritmus,rand()
je aliasmt_rand()
asrand()
je aliasmt_srand()
- ext/curl bude podporovat HTTP/2 Server Push
Závěr
Jak je vidět, tak oproti 7.0 jsou změny drobnější a zaměřené na vyladění stávající funkcionality. Upgrade by tedy neměl být složitý, ale stejně doporučuji počkat s produkčním nasazením alespoň na 7.1.1 ;-)
Pokud se vám ještě nepodařil upgrade na PHP 7.0, tak budu rád, pokud se v komentářích rozepíšete o tom, na čem jste se zasekli a co vás drží zpět.
Přehled komentářů