Développement PHP. Symfony Console Component - Trucs et astuces
Cet article a été créé dans le but de vous présenter les trucs et astuces les plus utiles et les plus récupérables concernant le développement de la console Symfony.
La nouvelle version de PHP arrive à grands pas. Quelles sont les nouvelles implémentations que vous devez connaître ? Consultez cet article pour le savoir !
PHP 8.2 est sur le point d'être publiée. Ce sera peut-être la version qui rendra la mise à niveau vers PHP 8 attrayante pour tout le monde. Voyons ce que les développeurs peuvent attendre de la version PHP 8.2 et se préparer à sa dernière version. Mais tout d'abord, passons rapidement en revue toutes les versions du PHP et les changements intervenus au fil des ans.
<?php
classe Utilisateur {
public int $id ;
public string $name ;
}
?>
<?php
$factor = 10 ;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]) ;
// $nums = array(10, 20, 30, 40) ;
?>
<?php
class A {}
class B extends A {}
class Producer {
public function method() : A {}
}
class ChildProducer extends Producer {
public function method() : B {}
}
?>
<?php
$array['key'] ??= computeDefault() ;
// est à peu près équivalent à
if (!isset($array['key'])) {
$array['key'] = computeDefault() ;
}
?>
<?php
$parts = ['pomme', 'poire'] ;
$fruits = ['banane', 'orange', ...$parts, 'pastèque'] ;
// ['banane', 'orange', 'pomme', 'poire', 'pastèque'] ;
?>
<?php
// Retourne un tableau contenant tous les états nécessaires de l'objet.
public function __serialize() : array ;
// Restaure l'état de l'objet à partir du tableau de données donné.
public function __unserialize(array $data) : void ;
?>
Publiée en novembre 2020, la version 8.0 de PHP nous a apporté les meilleures fonctionnalités à ce jour :
htmlspecialchars($string, double_encode : false);
classe PostsController
{
#[Route("/api/posts/{id}", methods : ["GET"])]
public function get($id) { /* ... */ }
}
class Point {
public function __construct(
public float $x = 0.0,
public float $y = 0.0,
public float $z = 0.0,
) {}
}
classe Number {
public function __construct(
private int|float $number
) {}
}
new Number('NaN') ; // TypeError
echo match (8.0) {
'8.0' => "Oh non !",
8.0 => "C'est ce à quoi je m'attendais",
} ;
//> C'est ce que j'attendais
$country = $session?->user?->getAddress()?->country ;
enum Statut
{
case Draft ;
case Publié ;
cas Archivé ;
}
function acceptStatus(Status $status) {...}
classe BlogData
{
public readonly Status $status ;
public function __construct(Status $status)
{
$this->status = $status ;
}
}
$foo = $this->foo(...) ;
$fn = strlen(...) ;
classe Service
{
private Logger $logger ;
public function __construct(
Logger $logger = new NullLogger(),
) {
$this->logger = $logger ;
}
}
function count_and_iterate(Iterator&Countable $value) {
foreach ($value as $val) {
echo $val ;
}
count($value) ;
}
$response = $httpClient->request('https://example.com/') ;
print json_decode($response->getBody()->buffer())['code'] ;
PHP 8.2 introduit de nouvelles modifications visant à faciliter la vie du développeur et à optimiser son travail. Voici la liste des nouvelles fonctionnalités.
L'une des plus grandes améliorations de la nouvelle version de PHP est la possibilité de créer directement un en lecture seule
classe. Une classe décrite avec cette fonctionnalité la propagera automatiquement pour ses variables. Les classes DTO auront désormais un aspect propre et net !
readonly class InvoiceDTO
{
public function __construct(
public UUID $uuid,
public Issuer $issuer,
public DateTime $issuedAt,
) {}
}
Le deuxième grand changement est la dépréciation des variables dynamiques dans les classes. L'implémentation suivante lancera une dépréciation en PHP 8.2 et ErrorException
dans la future version du PHP.
class MyUser
{
public string $name ;
}
(...)
$myUser->name = 'Name' ; // OK
$myUser->surname = 'Surname' ; // deprecated / errorexception
Il convient de mentionner que les classes qui mettent en œuvre des Il n'y a pas d'autre solution que de faire appel à l'expertise d'un expert en la matière.
et La loi sur l'immigration et la protection des réfugiés (LIPR)
et les classes héritant directement de stdClass
peut toujours mettre en œuvre des méthodes magiques sans aucun obstacle.
Je vous renvoie également à un fil de discussion intéressant sur GitHuboù les développeurs du PHP-CS discutent de ce changement et de la nécessité de modifier leur outil populaire pour l'adapter à la nouvelle version du langage.
Enfin, vous pouvez désactiver ce comportement par le biais des annotations.
#[AllowDynamicProperties]
class MyUser
{
public string $name ;
}
$myUser->surname = 'Surname' ; // OK
nul
, vrai
et faux
Jusqu'à présent, les fonctions qui renvoyaient toujours un vrai
ou faux
a dû être décrite à l'aide d'un bool
type.
function alwaysTrue() : bool { return true ; }
A partir de maintenant, nous pouvons utiliser vrai
et faux
en tant que types simples dans les valeurs renvoyées par les fonctions.
function alwaysTrue() : true { return true ; }
(DNF) est une méthode standard d'organisation des expressions booléennes. Plus précisément, il s'agit de structurer une expression booléenne en une série de OU et de ET. Appliquée aux déclarations de type, elle permet d'écrire de manière standard des types Union et Intersection combinés que l'analyseur syntaxique peut gérer.
Il s'agit d'un changement important, car nous pouvons désormais avoir des types d'intersection nullables, par exemple :
function getFullName((HasName&HasSurname)|null $user) { ... }
Je ne suis pas un grand partisan de l'utilisation des Traits et un tel changement est purement cosmétique pour moi, d'autant plus qu'il ne permet pas d'utiliser les valeurs des Traits sans initialiser l'objet.
trait Foo {
public const FLAG_1 = 1 ;
protected const FLAG_2 = 2 ;
private const FLAG_3 = 2 ;
public function doFoo(int $flags) : void {
if ($flags & self::FLAG_1) {
echo 'Got flag 1' ;
}
if ($flags & self::FLAG_2) {
echo 'Got flag 2' ;
}
if ($flags & self::FLAG_3) {
echo 'Got flag 3' ;
}
}
}
L'un des changements les plus importants que j'attends avec impatience. Dans la dernière version de PHP, nous serons en mesure de marquer les variables en tant que SensitiveParameterValue
. Pourquoi devrions-nous le faire ?
Les traces de pile du PHP dans les exceptions sont très utiles pour le débogage, mais elles vous permettent de prévisualiser les valeurs des paramètres. Par exemple, imaginons que PDO code utilisé pour se connecter à une base de données. La trace de débogage ressemblerait à ce qui suit :
PDOException : SQLSTATE[HY000] [2002] No such file or directory in /var/www/html/test.php:3
Trace de pile :
#0 /var/www/html/test.php(3) : PDO->__construct('mysql:host=loca...', 'root', 'password')
#1 {main}
Après avoir utilisé Annotation #[SensitiveParameter]
notre trace de pile ne montrera plus la valeur de la variable.
fonction test(
$foo,
#[SensitiveParameter] $bar,
$baz
) {
throw new Exception('Error') ;
}
test('foo', 'bar', 'baz') ;
/*
Erreur fatale : Exception non prise : Erreur dans test.php:8
Trace de pile :
#0 test.php(11) : test('foo', Object(SensitiveParameterValue), 'baz')
#1 {main}
dans test.php sur la ligne 8
*/
En tant que l'auteur dit
La motivation première de ce changement est de permettre de récupérer les propriétés name et value là où les objets enum ne sont pas autorisés, comme les clés de tableaux. Nous pourrions travailler sur les tableaux afin qu'ils puissent être étendus pour autoriser les enums ou tous les objets comme clés, mais il est plus simple d'autoriser la récupération des propriétés des enums.
enum A : string {
case B = 'B' ;
const C = [self::B->valeur => self::B] ;
}
Auparavant, les méthodes statiques fonctionnaient comme suit :
DateTime::createFromImmutable() : DateTime
DateTimeImmutable::createFromMutable() : DateTimeImmutable
En PHP 8.2 il va être changé en :
DateTime::createFromImmutable() : static
DateTimeImmutable::createFromMutable() : static
Il s'agit d'un changement radical pour les créateurs de bibliothèques et/ou toutes les implémentations personnalisées de DateTime.
Il s'agissait de deux fonctions qui ne servaient pas leur but, puisqu'elles ne faisaient que convertir entre ISO-8859-1
et UTF-8
. Le manuel PHP suggère d'utiliser mb_convert_encoding
au lieu de cela.
C'est l'auteur de la RFC qui décrit le mieux la sensibilité à la langue :
Avant PHP 8.0, la locale de PHP était définie à partir de l'environnement. Lorsqu'un utilisateur installe Linux, il lui est demandé dans quelle langue il souhaite l'utiliser. L'utilisateur peut ne pas apprécier pleinement les conséquences de cette décision. Non seulement elle définit la langue de l'interface utilisateur pour les commandes intégrées, mais elle modifie également de manière omniprésente le fonctionnement de la gestion des chaînes de caractères dans la bibliothèque C. Par exemple, un utilisateur sélectionnant "turc" lors de l'installation de Linux constatera que les applications appelant toupper('i') obtiendront le I majuscule pointé (U+0130, "İ").
À l'ère des protocoles textuels standardisés, le langage naturel est une application minoritaire pour la conversion de casse. Mais même si l'utilisateur souhaitait une conversion de casse en langage naturel, il aurait peu de chances d'y parvenir avec strtolower(). En effet, elle traite la chaîne de caractères un octet à la fois, en transmettant chaque octet à la fonction tolower() de la bibliothèque C. Si l'entrée est UTF-8, de loin le choix moderne le plus populaire, strtolower() mutilera la chaîne, produisant typiquement un UTF-8 invalide en sortie.
PHP 8.0 a cessé de respecter les variables d'environnement locales. La locale est donc toujours "C", sauf si l'utilisateur appelle explicitement setlocale(). Cela signifie que l'essentiel des changements rétro-compatibles est déjà derrière nous. Toutes les applications qui dépendent de la locale du système pour convertir la casse des anciens jeux de caractères 8 bits ont été interrompues par la version PHP 8.0.
Cela signifie que toutes les fonctions ci-dessous effectueront la conversion ASCII des majuscules et minuscules à partir de PHP.8.2 :strtolower
, strtoupper
, stristr
, stripos
, strripos
, lcfirst
, ucfirst
, mots-clés
, str_ireplace
Nous avons de nombreuses façons d'intégrer des variables dans des chaînes de caractères dans PHP :
- Intégration directe de variables ("$foo")
- Accolades à l'extérieur de la variable ("{$foo}")
- Accolades après le signe du dollar ("${foo}")
- Variables ("${expr}", équivalent à (chaîne) ${expr})
Afin d'éviter toute confusion et tout abus, ils ne fonctionneront plus :
"Bonjour ${monde}" ;
Déclassé : L'utilisation de ${} dans les chaînes de caractères est obsolète.
"Bonjour ${(monde)}" ;
Déclassé : L'utilisation de ${} (variables) dans les chaînes de caractères est obsolète.
Il ne s'agit pas de tous les changements qui PHP 8.2 nous offrira. Malheureusement, nous n'avons toujours pas obtenu le support des types génériques, d'après ce que Nikita a dit, les génériques monomorphisés ajouteraient trop de surcharge de performance, et les génériques réifiés nécessitent de nombreux changements dans l'ensemble de la base de code. Ce qui est remarquable, cependant, c'est la discipline et la vision de l'équipe de produit. Les changements introduits dans les versions successives de la langue sont de plus en plus clairs, et les personnes intéressées remarqueront que PHP va dans la bonne direction, tant dans le domaine de la simplification syntaxique que dans celui de la prise en charge des nouveautés. Je m'attends à ce que, dès l'année prochaine, nous voyions des appelable
comme un type valide.