De feestdagen komen er weer aan, dus is het tijd voor een nieuwe versie van PHP, de server-side scripttaal die ons favoriete CMS WordPress aandrijft. In de aanloop naar de lancering van versie 8.4 op 21 november hebben de ontwikkelaars van PHP talloze vroege versies van de nieuwe codebase getoond, waaronder een handvol release candidates sinds een bevriezing van de functies in augustus.

Samen met de nieuwe functies, verbeteringen en afschrijvingen die we rond deze tijd van het jaar verwachten, zijn er in 2024 wijzigingen aangebracht in de releasecyclus van PHP, waarbij het einde van de beveiligingsreleases voor alle momenteel ondersteunde versies is gesynchroniseerd met het einde van het jaar in plaats van de GA-verjaardag.

Bovendien werd die ondersteuning met een jaar verlengd, wat betekent dat je PHP 8.4 veilig tot 2028 zou kunnen gebruiken (met twee jaar beveiligingsupdates en bugfixes en twee jaar alleen beveiligingsupdates).

Je staat waarschijnlijk te springen om te weten wat er nieuw is in deze release. Dus laten we snel beginnen!

Nieuwe features en verbeteringen in PHP 8.4

De nieuwe features in PHP 8.3 van vorig jaar lijken weinig voor te stellen in vergelijking met sommige toevoegingen in 8.4:

Property hooks

Property hooks zorgen voor een geheel nieuwe benadering van het omgaan met “getters” en “setters” in PHP objectgeoriënteerd programmeren (OOP), waardoor je de structuur van je klassebestanden kunt vereenvoudigen.

Als voorbeeld van wat property hooks kunnen vervangen, bevat de eenvoudige klasse hieronder de properties $size en $flavor. Ze hebben private zichtbaarheid om ze te beschermen tegen directe toegang buiten het resulterende object. Daarom bemiddelen publieke getter en setter methoden de toegang tot de properties:

class Coffee
{
    private string $size;
    private string $flavor;
    public function __construct(string $size, string $flavor) {
        $this->size   = $size;
        $this->flavor = $flavor;
    }

    // "Setting" coffee size and flavor
    public function setSize(string $size): void {
        $this->size = $size;
    }
    public function setFlavor(string $flavor): void {
        $this->flavor = $flavor;
    }

    // "Getting" coffee size and flavor
    public function getSize(): string {
        return $this->size;
    }
    public function getFlavor(): string {
        return $this->flavor;
    }
} // End of class

// Make some coffee
$coffee = new Coffee('Small', 'Pumpkin Spice');
print $coffee->getSize() . ' ' . $coffee->getFlavor(); // Prints "Small Pumpkin Spice"

// Change order
$coffee->setSize('Grande');
$coffee->setFlavor('Mocha');
print $coffee->getSize() . ' ' . $coffee->getFlavor(); // Prints "Grande Mocha"

Of misschien heeft je klasse veel properties en in plaats van veel getter- en setter methoden te schrijven, gebruik je PHP’s _get en _set magische methoden. Je zou het zelfs kunnen regelen in een ietwat rommelig switch statement zoals dit fragment hieronder.

// __set magic method example
public function __set(string $key, $value): void 
    switch ($key) {
        case 'size':
            $this->size = $value;
            break;
        case 'flavor':
            $this->flavor = $value;
            break;
        default:
            throw new InvalidArgumentException('Invalid input');
        }
}

// Later, we can change the coffee order like this:
$coffee->size = 'Grande';
$coffee->flavor = 'Mocha';

Welke oplossing je ook kiest, hoe meer properties je in je klasse hebt, hoe verder de code om ze te manipuleren verwijderd is van hun definities bovenaan je klassebestand. Bovendien kunnen sommige implementaties van de magische methoden _get en _set onverwacht toegang geven tot privé of beschermde properties in je object die je niet van plan was bloot te geven.

De nieuwe property hooks bundelt getter en setter functionaliteit met de properties zelf. In het property hooks voorbeeld hieronder zie je dat de $size en $flavor properties van de Coffee klasse nu openbaar zijn. Maar we hebben ook wat basic validatie toegevoegd aan de set hooks, waardoor ze zich onderscheiden van directe toewijzingen.

// Property definitions at the top of our Coffee class
class Coffee
{
    public string $flavor {
        set(string $value) {
            if (strlen($value) > 16) throw new InvalidArgumentException('Input is too long');
                $this->flavor = $value;
        }
    }

    public string $size {
        set(string $value) {
            if (! in_array($value, array(‘Small’, ‘Grande’))) throw new InvalidArgumentException('Not a valid size');
                $this->size = $value;
        }
    }

    // Rest of the Coffee class
}

// Define a coffee
$coffee = new Coffee();
$coffee->size = 'Grande';
$coffee->flavor = 'Pumpkin spice';

Op dezelfde manier, zoals je hieronder kunt zien, kan een get hook functionaliteit verpakken in wat een gewone verwijzing naar een object property lijkt te zijn.

// Simplified Coffee class
class Coffee
{
    public string $flavor {
        get { 
            return $this->flavor . ' Spice';
       }
    }
}

// Create a flavor 
$coffee = new Coffee();
$coffee->flavor = 'Pumpkin'; // Stores the value "Pumpkin"
print $coffee->flavor;       // Prints "Pumpkin Spice"

In tegenstelling tot de PHP magic method, kunnen property hooks worden gebruikt in interfaces en abstracte klassen. Een voorbeeld van een interface:

interface Coffee
{
    public string $size { get; set; }
    public string $flavor { get; set; }
}

Asymmetrische zichtbaarheid

Publiekelijk zichtbare getter- en settermethoden die we eerder hebben bekeken, vertegenwoordigen de traditionele benadering voor toegang tot privé en beschermde properties binnen hun klassen.

Een handige functie van PHP 8.4 is de mogelijkheid om een property verschillende niveaus van zichtbaarheid te geven, afhankelijk van de context waarin deze wordt benaderd. Een property kan dus openbaar zijn als deze wordt gelezen, maar privé of beschermd als deze wordt ingesteld.

Bekijk dit eens:

class Coffee
{
    public private(set) string $flavor = 'Pumpkin Spice';
}

$coffee = new Coffee();
print $coffee->flavor;     // Prints "Pumpkin Spice"
$coffee->flavor = 'Mocha';  // Error (visibility)

Hierboven is de property $flavor van de klasse openbaar, behalve in een setting context. Het is al vrij eenvoudig, maar asymmetrische zichtbaarheid heeft zelfs een shorthand:

class Coffee
{
    // public is assumed when the context is not setting
    private(set) string $flavor = 'Pumpkin Spice';
}

Je kunt property hooks en asymmetrische zichtbaarheid in combinatie gebruiken voor een enorme flexibiliteit in het werken met objectproperties van verschillende zichtbaarheid.

new chainen zonder haakjes

Nu we het toch over shorthands hebben, het callen van new en chaining methods vereiste vroeger dat de call tussen haakjes werd geplaatst, zoals dit:

$coffee = (new Coffee())->getFlavor()->getSize();

PHP 8.4 staat dit toe:

$coffee = new Coffee()->getFlavor()->getSize();

Het lijkt misschien een kleine verandering, maar door slechts twee haakjes te laten vallen is dit veel gemakkelijker te lezen en te debuggen.

Nieuwe functies voor het vinden van array-items

Van de afdeling “Bedoel je dat we dit niet al konden doen?”, introduceert PHP 8.4 de functie array_find(), die array-elementen kan doorzoeken naar members die voldoen aan voorwaarden die zijn uitgedrukt in een callback-functie. De functie retourneert de waarde van het eerste element dat voldoet aan de callback’s test.

De nieuwe versie bevat drie andere gerelateerde functies:

  • array_find_key(): Zoals array_find(), maar de retourwaarde is de sleutel van het overeenkomende element in plaats van de waarde van de elementen zelf.
  • array_all(): Geeft true terug als elk element in de geteste array overeenkomt met de test van de callback.
  • array_any(): Geeft true terug als ten minste één van de elementen in de array overeenkomt met de test van de callback.

Merk op dat de laatste twee functies booleaanse indicatoren teruggeven in plaats van array-keys of inhoud.

Hier zijn enkele snelle voorbeelden:

$array = [
    'a' => 'Mocha',
    'b' => 'Caramel',
    'c' => 'Maple',
    'd' => 'Pumpkin'
   ];

// Find the first flavor name that is 5 characters long
var_dump(array_find($array, function (string $value) {
    return strlen($value) == 5;
})); // Returns “Mocha,” even though “Maple” is the same length 

// Find the array key for the first flavor with a name longer than 5 characters.
var_dump(array_find_key($array, function (string $value) {
    return strlen($value) > 5;
})); // Returns “b”

// Check to see if any flavor name is less than 5 characters long
var_dump(array_any($array, function (string $value) {
    return strlen($value) < 5;
})); // Returns false

// Check to see if all flavor names are shorter than 8 characters
var_dump(array_all($array, function (string $value) {
    return strlen($value) < 8;
})); // Returns true

HTML5 parsing

HTM5 is de defacto standaard voor de structuur van moderne webpagina’s, maar PHP’s Document Object Model (DOM) parsing technologie was vastgelopen bij HTML 4.01.

In plaats van de bestaande klasse DOMDocument, die met de oudere HTML standaarden werkt, te upgraden, komt PHP 8.4 met een nieuwe klasse DomHTMLDocument die klaar is voor HTM5.

Je kunt de inhoud van een HTML5 pagina op deze manier importeren:

$document = DomHTMLDocument::createFromString($html)

Naast de constructor createFromString($html) hierboven, ondersteunt de klasse ook createFromFile($path) en createEmpty()

De nieuwe parser herkent semantische HTML5-tags zoals main, article en section die de meesten van ons nu wel kennen.

Multibyte trim functies

Een andere toevoeging in PHP 8.4 die lang op zich heeft laten wachten, is multibyte ondersteuning in trim functies:

  • mb_trim()
  • mb_ltrim()
  • mb_rtrim()

Net als de al lang bestaande PHP trim() functie, verwijdert mb_trim witruimte en sommige speciale tekens, zoals line feeds, van beide uiteinden van een string die multibyte tekens kan bevatten. De andere functies trimmen de linker- of rechteruiteinden van een string.

Afschrijvingen in PHP 8.4

Elke release van PHP brengt een waslijst aan functies met zich mee (sommige behoorlijk obscuur) die gemarkeerd zijn voor uiteindelijke verwijdering van het platform. Een meer in het oog springende deprecatie in PHP 8.4 is non-cookie session tracking.

Afschaffing van GET/POST sessies

Hoewel cookies over het algemeen de voorkeursmethode zijn voor het bijhouden van gebruikerssessies, heeft PHP het vastleggen van sessie-ID gegevens in GET/POST parameters ondersteund. Om het bijhouden van sessies via parameters in URL’s mogelijk te maken, is de PHP-instelling session.use_only_cookies uitgeschakeld en kan de instelling session.use_trans_sid worden ingeschakeld.

Met PHP 8.4 zullen beide toestanden van de instellingen een afschrijvingswaarschuwing triggeren die kan verschijnen in de logs van je website. Wanneer PHP 9 uitkomt, zullen deze instellingen niet langer beschikbaar zijn.

Andere afschrijvingen (en verwijderingen) in PHP 8.4

Hieronder staat een lijst met functionaliteiten die het team achter PHP 8.4 wil verwijderen. (Sommige bevatten links naar meer informatie over de functies…,

  • Formeel afgeschreven soft-deprecated DOMDocument en DOMEntity properties.
  • DOMImplementation::getFeature($feature, $version) verwijderd.
  • Constante DOM_PHP_ERR afgeschreven.
  • De “S” tag in unserialize().
  • session.sid_length en session.sid_bits_per_character afgeschreven.
  • SplFixedArray::__wakeup() afgeschreven.
  • Afschaffen xml_set_object() en xml_set_*_handler() met stringmethode-namen.
  • Null en false doorgeven aan dba_key_split().
  • Doorgeven van onjuiste gegevenstypen voor opties aan ext/hash functies.
  • Constanten SUNFUNCS_RET_STRING, SUNFUNCS_RET_DOUBLE, SUNFUNCS_RET_TIMESTAMP.
  • Eigen CSV escaping mechanisme afgeschreven.
  • Constante E_STRICT afgeschreven.
  • Afschrijving  strtok().
  • Terugsturen van niet-string waarden uit een gebruiker uitvoer handler afgeschreven.
  • Uitvoer produceren in een gebruikeruitvoerafhandeling afgeschreven.
  • Afschrijven file_put_contents() met $data als array.
  • Afschrijven mysqli_ping() en mysqli::ping()
  • mysqli_refresh() afgeschreven.
  • Afschrijven mysqli_kill().
  • De tweede parameter van mysqli_store_result().
  • Afschrijven lcg_value().
  • Afschrijven uniqid().
  • Afschrijven md5(), sha1(), md5_file(), en sha1_file().
  • Afschrijven doorgeven van E_USER_ERROR aan trigger_error().
  • Afschrijven van het gebruik van een enkele underscore (“_”) als klassenaam.
  • De constante SOAP_FUNCTIONS_ALL afgeschreven en doorgeven aan SoapServer::addFunction().

Samenvatting

PHP 8.4 bevat een aantal interessante veranderingen. We zijn enthousiast om deze release binnenkort op onze servers te zetten voor onze jaarlijkse PHP benchmarking – onze tests met verschillende op PHP gebaseerde content management systemen.

We zijn ook benieuwd wanneer ontwikkelaars de nieuwe functies van PHP 8.4 in hun projecten gaan gebruiken, met name property hooks.

Welke PHP 8.4 functies zijn jouw favorieten? Deel je gedachten met onze community in de comments!

Steve Bonisteel Kinsta

Steve Bonisteel is Technical Editor bij Kinsta. Hij begon zijn schrijverscarrière als verslaggever en achtervolgde ambulances en brandweerwagens. Sinds eind jaren negentig schrijft hij over internetgerelateerde technologie.