Travaillons ensemble !

Services

Les nouveautés de PHP 7.4

La version 7.4 de PHP met à disposition des développeurs plusieurs améliorations au niveau performance et en terme de syntaxe. Beaucoup de concepts ont été introduits pour faciliter et moderniser encore plus l’écriture du code.


Propriétés typées 2.0

PHP 7.0 a permis de définir des types pour les arguments et les variables de retour des méthodes. Il manquait donc la possibilité de définir les types pour les propriétés de classes, ce qui fait que la communauté PHP a eu recours aux getters et setters pour forcer les types des propriétés. Exemple : 

class User {
    /** @var int $id */
    private $id;
    /** @var string $name */
    private $name;
 
    public function __construct(int $id, string $name) {
        $this->id = $id;
        $this->name = $name;
    }
 
    public function getId(): int {
        return $this->id;
    }
    public function setId(int $id): void {
        $this->id = $id;
    }
 
    public function getName(): string {
        return $this->name;
    }
    public function setName(string $name): void {
        $this->name = $name;
    }
}

PHP 7.4 permet donc d’avoir cette possibilité, ce qui va réduire l’implémentation de l’exemple précédent tout en offrant plus de clarté au code :

class User {
    public int $id;
    public string $name;
 
    public function __construct(int $id, string $name) {
        $this->id = $id;
        $this->name = $name;
    }
}

Il s’agit donc d’une nouveauté phare dont peut profiter pleinement les frameworks PHP pour moderniser leurs codebase.
Les types supportés sont bool, int, float, string, array, object, iterable, self, parent, n’importe quel nom de classe ou interface ainsi que les types nullable (?type). Les propriétés peuvent aussi avoir des valeurs par défaut lors de la déclaration en respectant bien-sûr les types déclarés. Seuls les types nullables peuvent avoir la valeur null comme valeur par défaut. Exemple :

class Test {
    public bool     $a = true;
    public int      $b = 42;
    public float    $c = 42.42;
    public string   $e = "str";
    public array    $f = [1, 2, 3];
    public iterable $g = [1, 2, 3];
    public ?int     $h = null;
    public ?object  $i = null;
    public ?Test    $j = null;
}

Si une propriété typée n’a pas de valeur par défaut, aucune valeur ne lui sera affectée lors de l'exécution, même si la propriété est nullable. Dans ce cas une erreur de type TypeError sera retournée lors de l’accès à cette propriété (sauf dans le cas d’une implémentation implicite via la méthode magique __get()).

Le pré-chargement (Preloading)

 

PHP s’appuie depuis toujours sur le cache opcode avec ses différentes implémentations (Zend OpCache, APC,..) pour rendre l'exécution du code plus rapide. Sur PHP 7.4 on introduit une nouvelle technique appelée Preloading qui permet de spécifier explicitement les fichiers PHP à inclure au moment du démarrage du serveur, en rendant leurs contenus (classes, fonctions,..) disponible pour toutes les applications qui tournent sur ce serveur.
Le pré-chargement est géré depuis la directive opcache.preload dans php.ini qui prend comme valeur le chemin d’un fichier PHP qui gère le chargement. D’autres fichiers peuvent être pré-chargé soit en utilisant des inclusions ou bien en utilisant la fonction opcache_compile_file().
Cette technique a comme inconvénient que pour chaque modification des fichiers pré-chargés, il faudra redémarrer le serveur pour prendre en compte les nouveaux changements.

Fonctions fléchées 2.0


Les fonctions anonymes introduites dans PHP 5.3 sont difficiles à maintenir et nous imposent une syntaxe longue et non intuitive. PHP 7.4 propose une syntaxe plus simple, inspirée des fonctions fléchées de Javascript. Prenons donc cet exemple :

function array_values_from_keys($arr, $keys) {
    return array_map(function ($x) use ($arr) { return $arr[$x]; }, $keys);
}

Ici la syntaxe ne donne pas beaucoup d’importance à l’opération de retour $arr[$x]; à cause de la syntaxe trop verbeuse. En alternative, la nouvelle syntaxe permet d’écrire la même fonctionnalité comme suit :

function array_values_from_keys($arr, $keys) {
    return array_map(fn($x) => $arr[$x], $keys);
}

L’utilisation du mot-clé “use” est maintenant obsolète. Si une variable utilisée dans l’expression appartient au scope parent, elle sera capturée par valeur automatiquement.

Opérateur Spread pour les tableaux


L’opérateur Spread est supporté pour les tableaux dans les appels des fonctions depuis PHP 5.6. Voici un exemple : 

function test(...$args) { var_dump($args); }
 
test(1, 2, 3);   // [1, 2, 3]
// Les arguments sont donc capturés dans un seul tableau $args

Sur PHP 7.4 nous avons la possibilité d’utiliser cette expression pour les tableaux et objets implémentant l’interface Traversable pas seulement dans les appels des fonctions :

$parts = ['apple', 'pear'];
$languages = ['banana', 'orange', ...$parts, 'watermelon']; // ['banana', 'orange', 'apple', 'pear', 'watermelon'];

Références faibles (WeakReference)

 

Dans PHP, les objets ne sont pas stockés dans les variables auxquelles ils sont assignées, mais plutôt les variables stockent des références vers ces objets. Avant PHP 7.4, il existait un seul type de référence qu’on appelle “Référence forte”, car tant qu’il y a une variable qui pointe vers un objet, ce dernier ne sera pas détruit par le ramasse-miettes (Garbage Collector, GC) :

$object = new stdClass;
$strongRef = $object;

var_dump($strongRef);  // Retourne object(stdClass)#1 (0) {}
unset($object);
var_dump($strongRef); // Retourne object(stdClass)#1 (0) {}

PHP 7.4 embarque la nouvelle classe WeakReference, permettant de définir des Références faibles vers des objets. On utilise pour cela les 2 méthodes create($object) et get() de cette classe :

$object = new stdClass;
$weakRef = WeakReference::create($object);

var_dump($weakRef->get());  // Retourne object(stdClass)#1 (0) {}
unset($object);
var_dump($weakRef->get()); // Retourne NULL car l’objet de référence est détruit.

Ce mécanisme permettra une bonne gestion de la mémoire surtout dans le cas des scripts qui traitent de gros volumes de données (batches, ...).


Opérateur de fusion null


PHP 7 a introduit la notion d’opérateur de fusion “??” comme alternative à l’utilisation d’un opérateur ternaire avec la fonction isset(). On retourne donc le premier opérateur s’il existe et n’est pas null, sinon on retourne le deuxième opérateur :

$username = $_GET['user'] ?? 'nobody';

Dans le cas où la taille de l’opérateur est longue et pour une self-affectation, on aura une expression qui ressemble à cela :

$this->request->data['comments']['user_id'] = $this->request->data['comments']['user_id'] ?? 'value';

Avec PHP 7.4, cette expression peut être réduite en utilisant le nouvel opérateur “??=” :

$this->request->data['comments']['user_id'] ??= 'value';

Dépréciations..

 

Pour préparer la sortie de la prochaine version majeure 8.0, PHP 7.4 embarque plusieurs dépréciations dans le but d’améliorer l’écosystème et d'éliminer les notions qui portent confusion aux développeurs. On note dans ce cas le type de variables “real” qui ne sera plus supporté dans la prochaine version majeure ainsi que l’utilisation de la fonction array_key_exists() avec des objets. Dans ce lien vous trouverez la liste complète des dépréciations de cette nouvelle version : https://wiki.php.net/rfc/deprecations_php_7_4.

Conclusion

 

On voit bien que PHP ne cesse pas de s’enrichir avec des mécanismes et notions modernes au niveau de la syntaxe et aussi au niveau des performances. Ceci ouvrira de nouvelles possibilités aux développeurs et communautés de frameworks et librairies pour moderniser leurs applications et outils, tout en gardant un oeil sur la prochaine version majeure du langage.