De PHP Group heeft versie 8.5 uitgebracht van de open source scripttaal die een groot deel van het web aandrijft, waaronder sites die het WordPress CMS gebruiken.
De release van PHP 8.5 in november markeerde het tweede jaar van het streven van de PHP community om jaarlijks grote updates uit te brengen, gevolgd door twee volle jaren van actieve ondersteuning voor elke release.
Hoewel 8.5 gloednieuw is, hebben we er al aandacht aan besteed in onze jaarlijkse PHP benchmarking achter verschillende populaire CMS platforms en frameworks.
Als je van plan bent om PHP applicaties te migreren naar versie 8.5, wil je natuurlijk weten wat er is veranderd in deze nieuwste release. En we denken dan meteen aan nieuwe features die je misschien kunt gebruiken om je code te verbeteren en oude functionaliteit die de ontwikkelaars van PHP willen verwijderen.
Dit zijn naar onze bescheiden mening de hoogtepunten van de nieuwe release:
Nieuwe features en verbeteringen in PHP 8.5
Laten we beginnen met nieuwe toevoegingen aan de PHP codebase. Deze wijzigingen beginnen meestal als Requests for Comments (RFC’s) die uiteindelijk kunnen worden goedgekeurd en toegewezen aan een toekomstige PHP release.
De nieuwe functies die hieronder worden beschreven, trekken de meeste aandacht rondom PHP 8.5.
Functie-calls chainen met een pipe operator
Een nieuwe pipe (|>) operator chaint functie-calls op een manier die JavaScript-programmeurs vaag bekend in de oren zal klinken. De pipe werkt van links naar rechts en geeft bij elke stap een enkele waarde door langs de chain.
Met vorige versies van PHP konden programmeurs een vergelijkbare taak uitvoeren door functies te nesten of door een reeks functie-calls te doorlopen op de geretourneerde waarde van elke stap.
Hier is een eenvoudig voorbeeld waarbij de nieuwe pipe operator wordt gebruikt:
$text = ' New-in-php-8.4 ';
$result = $text
|> trim(...)
|> (fn($str) => str_replace('4', '5', $str))
|> (fn($str) => str_replace('-', ' ', $str))
|> strtoupper(...);
var_dump($result);
// string(14) "NEW IN PHP 8.5"
(Merk op dat we de eersteklas callable syntax gebruiken (...) geïntroduceerd in PHP 8.1 met de trim() en strtoupper() functie-calls)
De pipe-chain hierboven zou op een enkele regel geschreven kunnen worden, maar leesbaarheid zou een van de voordelen van deze nieuwe operator moeten zijn.
Het bovenstaande komt overeen met het nesten van deze bewerkingen (in omgekeerde volgorde) op deze manier:
$text = " New-in-php-8.4 ";
$result = strtoupper(
str_replace(‘-, ' ',
str_replace('4', '5',
trim($text)
)
)
);
Als alternatief zou een programmeur de taak in eerdere PHP-versies op deze manier kunnen hebben uitgevoerd:
$text = " New-in-php-8.4 ";
$result = trim($text);
$result = str_replace('4', '5', $result);
$result = str_replace(‘-, ' ', $result);
$result = strtoupper($result);
URL’s parsen met de nieuwe URI-extensie
URL’s (ook wel URI’s genoemd voor degenen die nauwkeuriger zijn) zijn essentieel voor navigatie op het web, maar de functie parse_url() die sinds versie 4 in PHP is ingebouwd, staat erom bekend problemen te hebben met misvormde invoer die kan leiden tot fouten bij het proberen te manipuleren of valideren van websiteadressen.
Om het parsen van URL’s te verbeteren, bevat PHP 8.5 de libraries uriparser en Lexbor voor ondersteuning van respectievelijk RFC 3986 en WHATWG URL-standaarden.
Je kunt de uniparser library callen door op deze manier met de nieuwe URI extensie te beginnen:
$uri = new UriRfc3986Uri("https://kinsta.com/blog/php-8-5/");
echo $uri->getScheme(); // https
echo $uri->getHost(); // kinsta.com
echo $uri->getPath(); // /blog/php-8-5
Als alternatief kun je de Lexbor WHATWG URL library kiezen als volgt:
$uri = new UriWagWgUrl("https://kinsta.com/blog/php-8-5/");
echo $uri->getScheme(); // https
echo $uri->getUnicodeHost(); // kinsta.com
echo $uri->getAsciiHost(); // kinsta.com
echo $uri->getPath(); // /blog/php-8-5
De bovenstaande voorbeelden zijn de meest basale. De twee libraries die worden vertegenwoordigd door de URI-extensie in PHP 8.5 delen een aantal functionaliteiten en bevatten ook belangrijke verschillen.
Een belangrijk verschil is dat de RFC 3986 library zowel “raw” als “normalized-decoded” representaties van URI’s ondersteunt. Dit kan handig zijn bij het werken met percent-decoded invoer en uitvoer. Gebruikt in een browser, bijvoorbeeld, zijn deze twee URI’s identiek:
In vorige versies van PHP kon je beginnen met rawurldecode() en rawurlencode() (die ook RFC 3986 compliant zijn), maar de nieuwe extensie is klaar om met alle componenten van URI’s te werken, of ze nu gecodeerd zijn of niet.
Hier zijn enkele voorbeelden rechtstreeks uit de RFC achter de nieuwe parsing API:
$uri = new UriRfc3986Uri("https://%61pple:p%61ss@ex%61mple.com/foob%61r?%61bc=%61bc");
echo $uri->getRawUserInfo(); // %61pple:p%61ss
echo $uri->getUserInfo(); // apple:pass
echo $uri->getRawUsername(); // %61pple
echo $uri->getUsername(); // apple
echo $uri->getRawPassword(); // p%61ss
echo $uri->getPassword(); // pass
echo $uri->getRawHost(); // ex%61mple.com
echo $uri->getHost(); // example.com
echo $uri->getRawPath(); // /foob%61r
echo $uri->getPath(); // /foobar
echo $uri->getRawQuery(); // %61bc=%61bc
echo $uri->getQuery(); // abc=abc
Bij gebruik van de WHATWG URL library met de nieuwe extensie worden alle URI’s als “raw” behandeld, dus er is geen aparte set functies om alternatieve opmaak te ondersteunen. Maar de library kan converteren tussen ASCII en Unicode karakters die vaak voorkomen in URI’s.
Wees streng met een nieuwe max_memory_limit INI richtlijn
Ze zeggen dat wanneer iemand veel macht heeft, daar ook een dosis verantwoordelijkheid aan vastzit. Als die macht ook inhoudt dat je moet kiezen hoeveel servergeheugen je PHP applicatie probeert te gebruiken, kun je verantwoordelijk zijn voor crashes van applicaties wanneer processen meer geheugen gebruiken dan er beschikbaar is.
Een onderdeel van een typische PHP installatie is een php.ini bestand met configuratie-informatie dat een richtlijn bevat die een geheugengebruikslimiet specificeert voor elk PHP proces (of thread). Een veelgebruikte INI directive voor een geheugenlimiet van 128 MB ziet er als volgt uit:
// php.ini
memory_limit 128M
Op sommige hostingplatforms kunnen ontwikkelaars van PHP-applicaties memory_limit on the fly overschrijven met de functie ini_set() in hun code:
ini_set(‘memory_limit’, ‘256M’);
// Start code that requires up to 256 MB of memory
Je kunt de functie ook de waarde -1 geven, zoals ini_set('memory_limit', '-1') – om helemaal geen limiet op te leggen.
Het overschrijven van de INI directive voor een geheugenlimiet kan riskant zijn voor ontwikkelaars die niet goed bekend zijn met de geheugenconfiguraties van de servers waarop hun applicaties draaien. Als een of meerdere PHP threads proberen meer dan de totale geheugenpool te gebruiken, kan het resultaat een applicatiecrash zijn zonder waarschuwing tijdens het draaien.
PHP 8.5 voegt een max_memory_limit INI richtlijn toe die dient als een hard plafond, zelfs in setups waar ontwikkelaars toegang hebben tot init_set() om het geheugengebruik in hun code aan te passen.
Hier zijn voorbeelditems in het php.ini bestand van een PHP 8.5 installatie:
// php.ini
max_memory_limit 256M
memory_limit 128M
Met een max_memory_limit van 256 MB gebeurt er het volgende in onze PHP code:
ini_set('memory_limit', '256M'); // This is OK
ini_set('memory_limit', '512M'); // Fail with warning
ini_set('memory_limit', '-1'); // Fail with warning
Pogingen om een nieuwe geheugenlimiet van 512 MB (of onbeperkt) in te stellen zullen geen succes hebben. In plaats daarvan zal PHP de geheugenlimiet instellen op de waarde die is toegewezen aan max_memory_limit in het bestand php.ini en een waarschuwing geven. (De waarschuwing kan op het scherm verschijnen en gelogd worden, afhankelijk van de instellingen voor foutrapportage van de PHP installatie)
Een verstandige aanpak voor PHP 8.5 ontwikkelaars zou zijn om de ini_get() functie te gebruiken om te zien of de nieuwe maximale limiet is gedefinieerd, zoals ini_get('max_memory_limit') – en dan aan te passen aan de hand van de geretourneerde waarde. Met PHP-versies van voor 8.5 zou die aanroep veilig false retourneren.
De eerste of laatste waarden in een array pakken
Steek je hand op als je zou aannemen dat PHP al functies had om de waarden te lezen die zijn opgeslagen als de eerste of laatste leden van een array.
Het blijkt van niet. Maar sinds PHP 7.3 heeft het functies om de eerste en laatste keys in een array te achterhalen. Dus om de eerste en laatste waarden te vinden, kun je de functies array_key_first() of array_key_last() gebruiken en dan de teruggegeven keys gebruiken om te verwijzen naar de waarden die je zoekt:
$array = ["One", "Two", "Three"];
echo $array[array_key_first($array)]; // "One"
PHP 8.5 elimineert een stap voor die taak en stelt je in staat om de waarden direct te bereiken met de nieuwe array_first() en array_last() functies.
Het is allemaal heel eenvoudig:
$array = ["One", "Two", "Three"];
echo array_first($array); // "One"
echo array_last($array); // "Three"
echo array_last([]); // null
Hierboven kun je zien dat een lege array null retourneert, maar dat alleen bevestigt nog niet dat de hele array leeg is, omdat een arraywaarde null kan zijn:
echo array_last([1, 2, null]); // null
Eraan herinnerd worden om de retourwaarde van een functie te gebruiken
PHP 5.8 voegt een nieuw #[NoDiscard] attribuut toe dat aangeeft dat de retourwaarde van een functie mogelijk kritiek is. PHP zal controleren of de retourwaarde op de een of andere manier wordt gebruikt en, zo niet, een waarschuwing geven.
Een eenvoudig voorbeeld:
#[NoDiscard("this message property will be appended to the built-in warning.")]
function foo(): string {
return 'bar';
}
// Warning:
// The return value of function foo() is expected to be consumed,
// this message property will be appended to the built-in warning.
foo();
// This will not trigger a warning:
$result = foo();
// Also satisfactory is the (void) cast:
(void) foo();
In het bovenstaande voorbeeld wordt de retourwaarde van de gedefinieerde functie in eerste instantie helemaal niet gebruikt, waardoor een waarschuwing wordt geactiveerd. Maar wanneer de waarde wordt toegewezen aan de variabele $result of wordt gecast als void, wordt de waarde geacht te zijn geconsumeerd.
De auteurs van de RFC achter deze toevoeging aan PHP 8.5 beschreven dwingender toepassingen voor dit attribuut dan het eenvoudige voorbeeld hierboven. Eén scenario was een kritieke functie met een complexere foutmelding dan een eenvoudige pass/fail, en het beste overgebracht via de retourwaarde van de functie.
Andere verbeteringen met betrekking tot attributen
Naast het nieuwe #[NoDiscard] attribuut, zijn er nog andere verbeteringen aan de attribuut metadata functionaliteit in de nieuwe release:
- Attributen kunnen nu gericht zijn op constanten.
- Het
#[Override]attribuut kan nu worden toegepast op properties. - Het
#[Deprecated]attribuut kan worden gebruikt op properties en constanten. - Een nieuw
#[DelayedTargetValidation]attribuut kan worden gebruikt om compileerfouten te onderdrukken van core en extension attributen die worden gebruikt op ongeldige doelen.
Afschrijvingen en verwijderingen in PHP 8.5
Bij elke PHP release hoort een lijst met functionaliteiten die gemarkeerd zijn voor verwijdering in toekomstige versies. Het gebruik van afgeschreven functies in je code zal waarschuwingen triggeren. Als ze uiteindelijk uit PHP worden verwijderd, kan het gebruik ervan leiden tot fatale fouten.
Hier zijn enkele opvallende elementen die zijn afgeschreven of verwijderd in PHP 8.5:
- De backtick operator als alias voor
shell_exec()is afgeschreven. - Niet-canonieke castnamen
(boolean),(integer),(double), en(binary)zijn afgeschreven. Gebruik in plaats daarvan(bool),(int),(float), en(string). - De disable_classes INI instelling is verwijderd omdat deze ervoor zorgt dat verschillende aannames van de engine worden verbroken.
- Het beëindigen van
casestatements met een puntkomma in plaats van een dubbele punt is afgeschreven. - Het gebruik van null als array offset of bij het callen van
array_key_exists()is nu afgeschreven. Gebruik in plaats daarvan een lege string. - Het is niet langer mogelijk om “array” en “callable” te gebruiken als klasse alias namen in
class_alias(). - De magic methods
__sleep()en__wakeup()zijn soft-afgeschreven (soft-deprecated). In plaats daarvan moeten de magic methods__serialize()en__unserialize()worden gebruikt. - Er wordt nu een waarschuwing gegeven bij het casten van NAN naar andere typen.
- Het destructureren van niet-array waarden (anders dan null) met
[]oflist()geeft nu een waarschuwing. - Er wordt nu een waarschuwing gegeven bij het casten van floats (of strings die op floats lijken) naar
intals ze niet als één kunnen worden gerepresenteerd.
Samenvatting
Dat was een blik op de hoogtepunten van de PHP 8.5 release. We zijn ervan overtuigd dat de nieuwe pipe operator en verbeterde URI parsing populair zullen zijn bij ontwikkelaars. Misschien zelfs de nieuwe functies array_first() en array_last(), waar we geld op zouden hebben ingezet dat ze al bestonden.
Maar elke nieuwe PHP release bevat honderden wijzigingen. Je kunt een complete lijst van PHP 8.5 updates vinden in de officiële GitHub repository van de PHP Group.
Ondertussen zijn we hier bij Kinsta bezig om PHP 8.5 beschikbaar te maken voor onze WordPress hostingklanten. Wanneer dat online is, kun je overschakelen naar de nieuwe versie met behulp van onze PHP-instellingen.