IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

PHP 8 est disponible et s'accompagne d'optimisations et de nouvelles fonctionnalités, incluant entre autres les arguments nommés,
Les types d'union, l'opérateur nullsafe, la compilation JIT

Le , par Stéphane le calme

334PARTAGES

23  0 
PHP 7.4 a été publié en décembre dernier et l’équipe de développement du langage a présenté la nouvelle version majeure PHP 8. Nous y retrouvons entre autres :
  • de nouvelles fonctionnalités :
    • un compilateur JIT ;
    • les « union types » ;
    • les attributs ;
    • une nouvelle classe WeakMap ;
    • les simplifications de code apportées par les nouveaux constructeurs ;
  • de nouvelles fonctions :
    • des changements qui auront un impact sur le code existant (Breaking changes) ;
    • la gestion de l’incrémentation d’index négatifs dans les tableaux ;
    • des modifications sur la gestion des erreurs ;
    • des modifications sur les valeurs par défaut des directives d’initialisation de PHP ;
    • des fonctions supprimées.


Cette version contient donc beaucoup de nouvelles fonctionnalités et d'optimisations, incluant les arguments nommés, les types d'union, attributs, promotion de propriétés de constructeur, l'expression match, l'opérateur nullsafe, JIT (Compilation à la Volée), et des améliorations dans le système de typage, la gestion d'erreur, et de cohérence.

Compilation juste à temps (JIT)

PHP 8 introduit deux moteurs de compilation JIT (juste à temps/compilation à la volée). Le Tracing JIT, le plus prometteur des deux, montre environ trois fois plus de performances sur des benchmarks synthétiques et 1,5-2 fois plus de performances sur certaines applications à longue durée d'exécution. Généralement les performances des applications sont identiques à PHP 7.4.


Contribution relative du JIT à la performance de PHP 8

Amélioration du système de typage et de la gestion d'erreur
  • vérification de type plus sévère pour les opérateurs arithmétiques et bit à bit ;
  • validation de méthode abstraite des traits ;
  • signature valide des méthodes magiques ;
  • reclassifications des avertissements du moteur ;
  • erreur fatale pour des signatures de méthodes incompatibles ;
  • l'opérateur @ ne silence plus les erreurs fatales ;
  • héritages avec les méthodes privées ;
  • type mixed ;
  • type de retour static ;
  • types pour les fonctions internes Discussion e-mail ;
  • objets opaques au lieu de ressources pour les extensions Curl, Gd, Sockets, OpenSSL, XMLWriter, et XML.

Opérateur Nullsafe

Au lieu de faire des vérifications conditionnelles de nul, vous pouvez utiliser une chaîne d'appel avec le nouvel opérateur nullsafe. Qui lorsque l'évaluation d'un élément de la chaîne échoue, l'exécution de la chaîne complète est terminée et la chaîne entière évaluée à null.

Ainsi, dans PHP 7 vous aviez

Code PHP : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
$country =  null; 
  
if ($session !== null) { 
  $user = $session->user; 
  
  if ($user !== null) { 
    $address = $user->getAddress(); 
  
    if ($address !== null) { 
      $country = $address->country; 
    } 
  } 
}

Dans PHP 8 vous avez son équivalent :

Code PHP : Sélectionner tout
$country = $session?->user?->getAddress()?->country;

Expression match

La nouvelle instruction match est similaire à switch et a les fonctionnalités suivantes :
  • Match est une expression, signifiant que son résultat peut être enregistré dans une variable ou retourné ;
  • les branches de match supportent uniquement les expressions d'une seule ligne, et n'a pas besoin d'une déclaration break ;
  • Match fait des comparaisons strictes.

Ainsi, dans PHP 7 vous aviez

Code PHP : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
switch (8.0) { 
  case '8.0': 
    $result = "Oh no!"; 
    break; 
  case 8.0: 
    $result = "This is what I expected"; 
    break; 
} 
echo $result; 
//> Oh no!

Et son équivalent en PHP 8

Code PHP : Sélectionner tout
1
2
3
4
5
echo match (8.0) { 
  '8.0' => "Oh no!", 
  8.0 => "This is what I expected", 
}; 
//> This is what I expected

Types d'union

Au lieu d'annotation PHPDoc pour une combinaison de type, vous pouvez utiliser les déclarations de types d'union native qui sont validées lors de l'exécution.

Ainsi, en PHP 7 vous aviez

Code PHP : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
  /** @var int|float */ 
  private $number; 
  
  /** 
   * @param float|int $number 
   */ 
  public function __construct($number) { 
    $this->number = $number; 
  } 
} 
  
new Number('NaN'); // Ok

Et son équivalent en PHP 8

Code PHP : Sélectionner tout
1
2
3
4
5
6
7
class Number { 
  public function __construct( 
    private int|float $number 
  ) {} 
} 
  
new Number('NaN'); // TypeError

Promotion de propriétés de constructeur

Moins de code redondant pour définir et initialiser les propriétés.

En PHP 7 vous aviez

Code PHP : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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; 
  } 
}

En PHP 8 vous avez

Code PHP : Sélectionner tout
1
2
3
4
5
6
7
class Point { 
  public function __construct( 
    public float $x = 0.0, 
    public float $y = 0.0, 
    public float $z = 0.0, 
  ) {} 
}

Attributs

Au lieu d'annotations PHPDoc, vous pouvez désormais utiliser les métadonnées structurées avec la syntaxe native de PHP.

En PHP 7 vous aviez

Code PHP : Sélectionner tout
1
2
3
4
5
/** 
* @Route("/api/posts/{id}", methods={"GET", "HEAD"}) 
*/ 
class User 
{

En PHP 8 vous avez

Code PHP : Sélectionner tout
1
2
3
#[Route("/api/posts/{id}", methods: ["GET", "HEAD"])] 
class User 
{

Les arguments nommés

Les arguments nommés permettent de passer des arguments à une fonction en fonction du nom du paramètre, plutôt que de la position du paramètre. Cela rend la signification de l'argument autodocumentée, rend les arguments indépendants de l'ordre et permet de sauter arbitrairement les valeurs par défaut.

Pour donner un exemple simple :

Code PHP : Sélectionner tout
1
2
3
4
5
//en utilisant des arguments de position:  
array_fill(0, 100, 50);  
  
//en utilisant des arguments nommés:  
array_fill(start_index: 0, num: 100, value: 50);

L'ordre dans lequel les arguments nommés sont passés n'a pas d'importance. L'exemple ci-dessus les passe dans le même ordre qu'ils sont déclarés dans la signature de la fonction, mais tout autre ordre est également possible :

Code PHP : Sélectionner tout
array_fill(value: 50, num: 100, start_index: 0);

Il est possible de combiner des arguments nommés avec des arguments positionnels normaux et il est également possible de ne spécifier que certains des arguments optionnels d'une fonction, quel que soit leur ordre :

Code PHP : Sélectionner tout
1
2
3
htmlspecialchars($string, double_encode: false);  
//Revient à la même chose que  
htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);

Il y a plusieurs avantages aux arguments nommés.

Ignorer les valeurs par défaut

Les arguments nommés vous permettent d'écraser directement uniquement les valeurs par défaut que vous souhaitez modifier. Prenons cet exemple :

Code PHP : Sélectionner tout
1
2
3
4
setcookie(  
    name: 'test',  
    expires: time() + 60 * 60 * 2,  
);

Sa signature de méthode est en fait la suivante :

Code PHP : Sélectionner tout
1
2
3
4
5
6
7
8
9
setcookie (   
    string $name,   
    string $value = "",   
    int $expires = 0,   
    string $path = "",   
    string $domain = "",   
    bool $secure = false,   
    bool $httponly = false,  
) : bool

Dans cet exemple, nous n'avions pas besoin de définir $value d'un cookie, mais nous devions définir une heure d'expiration. Les arguments nommés ont rendu cet appel de méthode un peu plus concis.

Code autodocumenté

L'avantage de l'autodocumentation du code s'applique même lorsque vous n'ignorez pas les arguments facultatifs. Par exemple, comparez les deux lignes suivantes :

Code PHP : Sélectionner tout
1
2
3
array_slice($array, $offset, $length, true);  
// et  
array_slice($array, $offset, $length, preserve_keys: true);

Si cet exemple n'était pas écrit en ce moment, un développeur n'aurait pas su ce que fait le quatrième paramètre de array_slice (ou même qu'il existe en premier lieu).

Initialisation d'objet

La RFC de promotion des propriétés du constructeur simplifie considérablement la déclaration des classes d'objets de valeur. Pour choisir l'un des exemples de cette RFC :

Code PHP : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Partie de la représentation PHP AST  
class ParamNode extends Node {  
    public function __construct(  
        public string $name,  
        public ExprNode $default = null,  
        public TypeNode $type = null,  
        public bool $byRef = false,  
        public bool $variadic = false,  
        Location $startLoc = null,  
        Location $endLoc = null,  
    ) {  
        parent::__construct($startLoc, $endLoc);  
    }  
}

Les constructeurs en particulier ont souvent un nombre plus grand que la moyenne de paramètres dont l'ordre n'a pas de signification particulière, et qui sont généralement par défaut. Bien que la promotion du constructeur simplifie la déclaration de classe, elle n'aide pas l'instanciation d'objet réelle.

Il y a eu plusieurs tentatives pour rendre la construction d'objets plus ergonomique, comme le RFC Object Initializer et le RFC COPA. Cependant, toutes ces tentatives ont été refusées, car elles ne s'intègrent pas bien dans le langage, en raison d'une interaction défavorable avec des constructeurs ou des propriétés non publiques.

Les arguments nommés résolvent le problème d'initialisation des objets comme un effet secondaire, d'une manière qui s'intègre bien à la sémantique du langage existant.

Code PHP : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
new ParamNode("test", null, null, false, true);  
// devient:  
new ParamNode("test", variadic: true);  
  
new ParamNode($name, null, null, $isVariadic, $passByRef);  
// ou était-ce ?  
new ParamNode($name, null, null, $passByRef, $isVariadic);  
// qui devient  
new ParamNode($name, variadic: $isVariadic, byRef: $passByRef);  
// ou  
new ParamNode($name, byRef: $passByRef, variadic: $isVariadic);  
// et cela n'a plus d'importance!

L'avantage des arguments nommés pour l'initialisation des objets est en surface le même que pour les autres fonctions, cela a juste tendance à avoir plus d'importance dans la pratique ici.

Options sécurisées et documentées

L'une des solutions de contournement courantes pour le manque d'arguments nommés est l'utilisation d'un tableau d'options. L'exemple précédent pourrait être réécrit pour utiliser un tableau d'options comme suit :

Code PHP : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class ParamNode extends Node {  
    public string $name;  
    public ExprNode $default;  
    public TypeNode $type;  
    public bool $byRef;  
    public bool $variadic;  
  
    public function __construct(string $name, array $options = []) {  
        $this->name = $name;  
        $this->default = $options['default'] ?? null;  
        $this->type = $options['type'] ?? null;  
        $this->byRef = $options['byRef'] ?? false;  
        $this->variadic = $options['variadic'] ?? false;  
  
        parent::__construct(  
            $options['startLoc'] ?? null,  
            $options['endLoc'] ?? null  
        );  
    }  
}  
  
// Usage:  
new ParamNode($name, ['variadic' => true]);  
new ParamNode($name, ['variadic' => $isVariadic, 'byRef' => $passByRef]);

Bien que cela fonctionne, et soit déjà possible aujourd'hui, cela présente de nombreux inconvénients :
  • pour les constructeurs en particulier, cela exclut l'utilisation de la promotion de constructeur ;
  • les options disponibles ne sont pas documentées dans la signature. Vous devez regarder l'implémentation ou phpdoc pour savoir ce qui est pris en charge et quels types il nécessite. Phpdoc ne fournit pas non plus de moyen universellement reconnu de documenter cela ;
  • le type des valeurs d'option n'est pas validé sauf s'il est implémenté manuellement. Dans l'exemple ci-dessus, les types seront en fait validés en raison de l'utilisation de types de propriétés, mais cela ne suivra pas la sémantique PHP habituelle (par exemple, si la déclaration de classe utilise strict_types, les options seront également validées selon strict_types) ;
  • à moins que vous ne fassiez tout votre possible pour vous protéger, le passage d'options inconnues sera validé silencieusement ;
  • l'utilisation d'un tableau d'options nécessite une décision spécifique au moment de l'introduction de l'API. Si vous commencez sans en utiliser un, mais ajoutez ensuite des paramètres facultatifs supplémentaires et réalisez que l'utilisation d'un tableau d'options serait plus propre, vous ne pouvez pas effectuer le changement sans interrompre les utilisateurs d'API existants.

Les paramètres nommés fournissent les mêmes fonctionnalités que les tableaux d'options, sans aucun des inconvénients.

Source : PHP

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de
https://www.developpez.com
Le 27/11/2020 à 11:42
Définir les propriétés de classe dans le constructeur me fait un peu mal aux yeux mais je pense que c'est une question d'habitude, dans quelques mois je trouverais la façon de faire actuelle inutilement complexe. J'aime ce nullsafe operator d'un amour pur, tant de lignes de codes vont être éradiquées par ce petit "?" De même le nouveau str_contains() qui fait plaisir niveau lisibilité du code au lieu des strpos() !== false. Je suspecte aussi que match sera très utilisé pour tout ce qui est texte conditionnel (locales par exemple), ce qui nous épargne des switchs infinis qui nécessitent des variables initialisées en amont.

Bref PHP sur la bonne voie, il manque plus qu'un façon simple de faire du server push
4  0 
Avatar de Cryde
Membre du Club https://www.developpez.com
Le 27/11/2020 à 14:51
Citation Envoyé par grunk Voir le message

Et j'avais pas vu , mais PHP se modernise même dans les changelog : https://www.php.net/releases/8.0/fr.php?lang=fr !
C'est des designeurs de Jetbrains qui ont proposé ça pour mieux "communiquer" sur cette nouvelle release.

Citation Envoyé par strato35 Voir le message
J'aurai bien aimé qu'ils rajoutent les génériques ou le cast vers un type objet à la liste :/
Quand dans symfony je type tout mais que j'ai des lignes rouges uniquement car je peux pas préciser que le find hérité de mon répo à un retour de tel type d'objet parce que je ne peux pas le cast ou parce que la méthode ne peux pas faire de return de type T c'est frustrant :/
Ils avaient commencé à le faire mais apparemment c'était trop gourmand niveau perf (https://wiki.php.net/rfc/generics)
3  0 
Avatar de floyer
Membre averti https://www.developpez.com
Le 28/11/2020 à 18:36
Citation Envoyé par xillibit Voir le message
Dans les versions 7.2.x à 7.4.x tu peux déjà utiliser des requêtes préparés pour éviter de faire des injections SQL
D’après https://www.php.net/manual/fr/pdosta....bindvalue.php les requêtes préparées sont accessibles en PHP5.1 et plus... je suis même surpris que cela ne soit pas en version 1 tellement les requêtes préparées me semblent le minimum attendu d’un pilote SGBD.
1  0 
Avatar de floyer
Membre averti https://www.developpez.com
Le 29/11/2020 à 11:33
Il y a 25 ans lorsque je faisais mon premier script Web-cgi, je m’inquiétais pour la sécurité comme je le ferais aujourd’hui. Vu que le script tourne avec des droits serveurs mais utilise des données qui peuvent être quelconques.

Les concepteurs de Perl (version 4 à l’époque) ne s’y sont pas trompés : on avait des variables teintées qui obligeaient le développeur à analyser les chaînes de caractères venant de l’extérieur avant de les utiliser.
1  0 
Avatar de laurentSc
Expert confirmé https://www.developpez.com
Le 26/11/2020 à 23:21
Citation Envoyé par rawsrc Voir le message
si le code n'a pas été pondu par un goret
Ca veut dire, pas par LaurentSc
0  0 
Avatar de grunk
Modérateur https://www.developpez.com
Le 27/11/2020 à 8:54
Les promotions d'argument de constructeur j'aime pas.
Les arguments nommé ont plein d'avantage , mais offre aussi la possibilité d'un beau bordel dans le code (genre appeler une fonction avec les arguments jamais dans le même sens) , ca va demander de la rigeur.

Le reste c'est plein de belles évolutions.

Et j'avais pas vu , mais PHP se modernise même dans les changelog : https://www.php.net/releases/8.0/fr.php?lang=fr !
0  0 
Avatar de xillibit
Membre régulier https://www.developpez.com
Le 27/11/2020 à 11:09
Citation Envoyé par djimtolouma Voir le message
Selon moi la nouvelle version de php nous donnera plus de posibilite de pouvoir faire de script sans faille securite dans le developpement avec l'integration du nouveu compilateur est vraiiment genial.J'encourage l'equipe a vraiment mettre a notre disposition le plus rapide cette version.
Dans les versions 7.2.x à 7.4.x tu peux déjà utiliser des requêtes préparés pour éviter de faire des injections SQL

L'opérateur @ ne silence plus les erreurs fatales.
ça dans certains scripts que j'utilise c'est utilisé à la pelle
0  0 
Avatar de strato35
Membre éclairé https://www.developpez.com
Le 27/11/2020 à 11:45
J'aurai bien aimé qu'ils rajoutent les génériques ou le cast vers un type objet à la liste :/
Quand dans symfony je type tout mais que j'ai des lignes rouges uniquement car je peux pas préciser que le find hérité de mon répo à un retour de tel type d'objet parce que je ne peux pas le cast ou parce que la méthode ne peux pas faire de return de type T c'est frustrant :/
0  0 
Avatar de floyer
Membre averti https://www.developpez.com
Le 28/11/2020 à 19:06
Dire que je freinais la migration d’un php7.2 à cause d’incompatibilités de SPIP... mon retard augmente.

On note un warning des php7 récents indiquant que les précédences des . et +/- changent en v8... il vaut mieux mettre des parenthèses !
0  0 
Avatar de valaendra
Membre éclairé https://www.developpez.com
Le 29/11/2020 à 10:12
Citation Envoyé par floyer Voir le message
D’après https://www.php.net/manual/fr/pdosta....bindvalue.php les requêtes préparées sont accessibles en PHP5.1 et plus... je suis même surpris que cela ne soit pas en version 1 tellement les requêtes préparées me semblent le minimum attendu d’un pilote SGBD.
L'approche "sécurité" était bien différente il y a 20 ans Puis PHP a commencé à être populaire à partir de sa version 3. PHP est aujourd'hui loin de son objectif initial : un langage de templating pour le web.

Concernant les attributs déclarés dans le constructeur, ça économise rien du tout et ça rend la lecture de la structure plus difficile (à mon humble avis).

Sinon pas vu dans le changelog (et pas encore testé) toujours pas de typage hors des classes ? (dans le contexte global par exemple...).
0  0