Sviluppo PHP. Componente console di Symfony - Suggerimenti e trucchi
Questo articolo è stato creato con l'obiettivo di mostrare i consigli e i trucchi più utili e interessanti sullo sviluppo di Symfony Console.
La nuova versione di PHP è alle porte. Quali sono le nuove implementazioni da conoscere? Consultate questo articolo per scoprirlo!
PHP 8.2 sta per essere rilasciata. Forse sarà la versione che farà sembrare a tutti interessante l'aggiornamento all'PHP 8. Parliamo di ciò che gli sviluppatori possono aspettarsi con PHP 8.2 e prepararsi alla sua ultima versione. Ma prima, passiamo rapidamente in rassegna tutte le versioni e i cambiamenti dell'PHP nel corso degli anni.
.
classe Utente {
public int $id;
public string $name;
}
?>
.
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);
// $nums = array(10, 20, 30, 40);
?>
.
classe A {}
la classe B estende A {}
classe Producer {
public function method(): A {}
}
class ChildProducer extends Producer {
public function method(): B {}
}
?>
.
$array['key'] ??= computeDefault();
// è approssimativamente equivalente a
if (!isset($array['key'])) {
$array['key'] = computeDefault();
}
?>
.
$parts = ['mela', 'pera'];
$fruits = ['banana', 'arancia', ...$parts, 'anguria'];
// ['banana', 'arancia', 'mela', 'pera', 'anguria'];
?>
.
// Restituisce un array contenente tutti gli stati necessari dell'oggetto.
public function __serialize(): array;
// Ripristina lo stato dell'oggetto dall'array di dati fornito.
public function __unserialize(array $data): void;
?>
Rilasciato nel novembre 2020, PHP 8.0 ci ha portato le migliori caratteristiche, tra cui:
htmlspecialchars($string, double_encode: false);
classe PostsController
{
#[Route("/api/posts/{id}", methods: ["GET"])]
public function get($id) { /* ... */ }
}
classe Punto {
funzione pubblica __construct(
public float $x = 0.0,
public float $y = 0.0,
public float $z = 0,0,
) {}
}
classe Numero {
public function __construct(
private int|float $number
) {}
}
new Number('NaN'); // TypeError
echo match (8.0) {
8.0' => "Oh no!",
8.0 => "Questo è ciò che mi aspettavo",
};
//> Questo è ciò che mi aspettavo
$country = $session?->user?->getAddress()?->country;
enum Stato
{
caso Bozza;
caso Pubblicato;
caso Archiviato;
}
function acceptStatus(Status $status) {...}
classe BlogData
{
public readonly Status $status;
public function __construct(Status $status)
{
$this->status = $status;
}
}
$foo = $this->foo(...);
$fn = strlen(...);
classe Servizio
{
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 introduce ulteriori modifiche volte a semplificare la vita dello sviluppatore e a ottimizzare ulteriormente il suo lavoro. Di seguito l'elenco delle nuove funzionalità.
Uno dei maggiori miglioramenti della nuova versione di PHP è la possibilità di creare direttamente un file di solo in lettura
classe. Una classe descritta con questa caratteristica la propagherà automaticamente per le sue variabili. Le classi DTO avranno ora un aspetto ordinato e pulito!
readonly classe InvoiceDTO
{
public function __construct(
public UUID $uuid,
public Emittente $issuer,
public DateTime $issuedAt,
) {}
}
Il secondo grande cambiamento è la deprecazione delle variabili dinamiche nelle classi. La seguente implementazione lancerà una deprecazione in PHP 8.2 e ErroreEccezione
nella versione futura dell'PHP.
classe MyUser
{
public string $name;
}
(...)
$myUser->nome = 'Nome'; // OK
$myUser->surname = 'Cognome'; // deprecata / errorexception
Vale la pena ricordare che le classi che implementano __gettare
e __set
e le classi che ereditano direttamente da stdClass
possono comunque implementare i metodi magici senza alcun ostacolo.
Qui vi rimando anche a un interessante thread su GitHubdove gli sviluppatori di PHP-CS discutono di questo cambiamento e della necessità di modificare il loro popolare strumento per la nuova versione del linguaggio.
Infine, è possibile disabilitare questo comportamento tramite l'annotazione.
#[AllowDynamicProperties]
classe MyUser
{
public string $name;
}
$myUser->cognome = 'Cognome'; // OK
nullo
, vero
, e falso
Finora, le funzioni che restituivano sempre un valore vero
o falso
è stato descritto con un valore bool
tipo.
function alwaysTrue(): bool { return true; }
D'ora in poi, possiamo usare vero
e falso
come tipi semplici nei valori restituiti dalle funzioni.
function alwaysTrue(): true { return true; }
(DNF) è un modo standard di organizzare le espressioni booleane. In particolare, significa strutturare un'espressione booleana in una serie di OR e AND. Applicato alle dichiarazioni di tipo, consente di scrivere in modo standard tipi combinati di Unione e Intersezione che il parser può gestire.
È un cambiamento importante, perché ora possiamo avere tipi di intersezione nullable, per esempio:
function getFullName((HasName&HasSurname)|null $user) { ... }
Non sono un grande sostenitore dell'uso dei Tratti e questa modifica mi sembra puramente estetica, soprattutto perché non consente di usare i valori dei Tratti senza inizializzare l'oggetto.
tratto Foo {
public const FLAG_1 = 1;
protected const FLAG_2 = 2;
private const FLAG_3 = 2;
public function doFoo(int $flags): void {
se ($flags & self::FLAG_1) {
echo 'Ottenuto il flag 1';
}
if ($flags & self::FLAG_2) {
echo 'Ottenuto flag 2';
}
se ($flags & self::FLAG_3) {
echo 'Ottenuto il flag 3';
}
}
}
Uno dei cambiamenti più importanti che attendo con ansia. Nell'ultima versione di PHP saremo in grado di contrassegnare le variabili come ValoreParametroSensibile
. Perché dovremmo?
Le tracce di stack dell'PHP nelle eccezioni sono molto utili per il debug, tuttavia consentono di visualizzare in anteprima i valori dei parametri. Per esempio, immaginiamo che PDO codice utilizzato per connettersi a un database. La traccia di debug appare come segue:
PDOException: SQLSTATE[HY000] [2002] No such file or directory in /var/www/html/test.php:3
Stack trace:
#0 /var/www/html/test.php(3): PDO->__construct('mysql:host=loca...', 'root', 'password')
#1 {main}
Dopo aver utilizzato l'annotazione #[SensitiveParameter]
la traccia dello stack non mostrerà più il valore della variabile.
funzione test(
$foo,
#[Parametro sensibile] $bar,
$baz
) {
lancia una nuova eccezione('Errore');
}
test('foo', 'bar', 'baz');
/*
Errore fatale: Eccezione non catturata: Errore in test.php:8
Traccia dello stack:
#0 test.php(11): test('foo', Object(SensitiveParameterValue), 'baz')
#1 {main}
lanciato in test.php alla riga 8
*/
Come l'autore dice
La motivazione principale di questa modifica è quella di consentire il recupero delle proprietà nome e valore in luoghi in cui gli oggetti enum non sono ammessi, come le chiavi degli array. Si potrebbe lavorare sugli array, in modo da estenderli per consentire l'uso di enum o di tutti gli oggetti come chiavi, ma permettere di recuperare le proprietà degli enum è più semplice.
enum A: stringa {
caso B = 'B';
const C = [self::B->value => self::B];
}
In precedenza i metodi statici funzionavano in questo modo:
DateTime::createFromImmutable(): DateTime
DateTimeImmutable::createFromMutable(): DateTimeImmutable
In PHP 8.2 sarà cambiato in:
DateTime::createFromImmutable(): statico
DateTimeImmutable::createFromMutable(): statico
Si tratta di una modifica di rottura per i creatori di librerie e/o per tutte le implementazioni personalizzate di DateTime.
Si trattava di due funzioni che non servivano allo scopo, in quanto convertivano soltanto tra ISO-8859-1
e UTF-8
. PHP Il manuale suggerisce di utilizzare mb_convert_encoding
invece.
La sensibilità alla localizzazione è descritta meglio dall'autore dell'RFC:
Prima di PHP 8.0, il locale di PHP era impostato dall'ambiente. Quando un utente installa Linux, gli viene chiesto in quale lingua vuole che sia scritto. L'utente potrebbe non apprezzare appieno le conseguenze di questa decisione. Non solo imposta la lingua dell'interfaccia utente per i comandi integrati, ma modifica anche in modo pervasivo il funzionamento della gestione delle stringhe nella libreria C. Per esempio, un utente che seleziona "Turco" quando installa Linux scoprirebbe che le applicazioni che chiamano toupper('i') otterrebbero la I maiuscola punteggiata (U+0130, "İ").
In un'epoca di protocolli standardizzati basati sul testo, il linguaggio naturale è un'applicazione minoritaria per la conversione delle maiuscole. Ma anche se l'utente volesse la conversione di maiuscole e minuscole in linguaggio naturale, è improbabile che riesca a ottenerla con strtolower(). Questo perché elabora la stringa un byte alla volta, fornendo ogni byte alla funzione tolower() della libreria C. Se l'input è UTF-8, di gran lunga la scelta moderna più diffusa, strtolower() manipolerà la stringa, producendo tipicamente UTF-8 non valido come output.
PHP 8.0 ha smesso di rispettare le variabili d'ambiente locale. Quindi il locale è sempre "C", a meno che l'utente non chiami esplicitamente setlocale(). Questo significa che la maggior parte delle modifiche di retrocompatibilità è già alle spalle. Tutte le applicazioni che dipendono dal locale di sistema per la conversione dei caratteri a 8 bit sarebbero state interrotte da PHP 8.0.
Ciò significa che tutte le funzioni sotto elencate eseguono la conversione dei casi ASCII da PHP.8.2:strtolower
, strtoupper
, stristr
, stripos
, strripos
, lcfirst
, ucfirst
, ucwords
, str_ireplace
In PHP abbiamo molti modi per incorporare le variabili nelle stringhe:
- Incorporazione diretta di variabili ("$foo")
- Parentesi graffe fuori dalla variabile ("{$foo}")
- Parentesi graffe dopo il segno del dollaro ("${foo}")
- Variabili ("${expr}", equivalente a (stringa) ${expr})
Per evitare confusione e usi impropri, questi non funzioneranno più:
"Ciao ${world}";
Deprecato: L'uso di ${} nelle stringhe è deprecato.
"Ciao ${(mondo)}";
Deprecato: L'uso di ${} (variabile variabile) nelle stringhe è deprecato.
Questi non sono tutti i cambiamenti che PHP 8.2 ci offrirà. Sfortunatamente, non abbiamo ancora ottenuto il supporto per i tipi generici: secondo quanto affermato da Nikita, i generici monomorfizzati aggiungerebbero troppo overhead alle prestazioni, mentre i generici reificati richiedono molti cambiamenti nell'intera base di codice. Ciò che si nota, tuttavia, è la disciplina e la visione del gruppo di lavoro prodotto. Le modifiche introdotte nelle versioni successive della lingua sono sempre più chiare e gli interessati noteranno che PHP si sta muovendo nella giusta direzione sia per quanto riguarda la semplificazione della sintassi che per il supporto alle novità. Mi aspetto che già l'anno prossimo vedremo richiamabile
come tipo valido.