PHP 7.2 presenta novità interessanti soprattutto dal punto di vista della sicurezza, oltre che alcune migliorie minori e un nuovo set di feature deprecate.
Argon2i
Iniziamo con la prima importante novità dedicata alla sicurezza che riguarda la funzione password_hash()
, introdotta con PHP 5.5 ma che fino ad ora aveva come unico supporto PASSWORD_BCRYPT
. PHP 7.2 introduce Argon2i come alternativa, si tratta di un algoritmo più moderno per il salvataggio delle password, particolarmente veloce e progettato per resistere ad attacchi. In particolare rispetto a PASSWORD_BCRYPT
può essere configurato secondo 3 parametri che ne stabiliscono il comportamento:
- Un "costo" che definisce l'utilizzo della memoria da parte dell'algoritmo.
- Un "costo" che definisce il tempo di esecuzione dell'algoritmo e il numero di iterazioni.
- Un fattore di parallelismo, che definisce il numero di thread paralleli.
Per esempio:
// Uso di Argon2i con i fattori di costo di default
password_hash('password', PASSWORD_ARGON2I);
// Uso di Argon2i con i fattori di costo personalizzati
password_hash('password', PASSWORD_ARGON2I, ['memory_cost' => 1 2]);
Altra importante differenza fra i due è che PASSWORD_ARGON2I
genera un hash di 96 caratteri contro i 60 di PASSWORD_BCRYPT
.
libsodium
L'altra grande novità per la sicurezza è la libreria di crittografia libsodium integrata nel core di PHP 7.2. Libsodium è facile da usare per la crittografia, la decrittografia, le firme e il password hashing. Il suo obiettivo è fornire tutte le operazioni fondamentali necessarie per costruire strumenti crittografici di livello superiore. In pratica esso mette a disposizione:
- Crittografia a chiave pubblica usando Diffie-Hellman e firme digitali su Curve25519.
- Interoperabilità con altri protocolli che utilizzano NaCl o libsodium (ad esempio Noise).
- La capacità di cancellare i buffer di memoria.
- Algoritmi di crittografia che non sono vulnerabili ai canali laterali in assenza di hardware dedicato.
- Crittografia autenticata.
Oggetti, tipi di dato e valori
Le novità significative non riguardano solo il tema della sicurezza, con PHP 7.2 sarà anche possibile passare a una funzione un oggetto come tipo di parametro e specificare un oggetto come dato restituito:
function miaFunzione(object $mioOggetto): object {
$obj = json_decode('{}');
return $obj;
}
Questo significa che nella versione 7.2 object
diventa una parola riservata e non può essere usata per nomi di classi o altro di simile, questo dovrebbe aiutare a generare codice più pulito e più facilmente testatbile.
Un'altra importante novità riguarda la possibilità di ignorare la dichiarazione dei tipi di dato nelle classi figlie
class PadreClass {
public function mioTest(string $parametro) { }
}
class FiglioClass extends PadreClass {
public function mioTest($parametro) { }
}
Fino ad ora PHP non permetteva di variare i tipi di parametro nelle classi figlie. Si è quindi deciso di omettere la dichiarazione del tipo nella classe figlia eliminando il rischio di rendere il codice malfunzionante durante l'estensione delle classi o l'implementazione delle interfacce. Ciò fornirà un percorso di aggiornamento più facile per le librerie per iniziare a utilizzare tipi scalari, per sostituire i controlli manuali effettuati all'interno dei metodi, senza richiedere un aggiornamento per tutte le sotto-classi.
Inoltre con PHP 7.2 sarà possibile contare valori scalari. In pratica la chiamata count()
su uno scalare o su un oggetto che non implementa l'interfaccia Countable
restituisce 1.
Altri cambiamenti minori sono
get_class()
con parametronull
.- Caricamento delle estensioni per nome omettendo l'estensione nel file
php.ini
- Uso di stringhe non quotate deprecato.
- Uso della virgola dopo l'ultimo elemento di un array.
Funzioni deprecate
Passiamo ora a ciò che la nuova versione rende deprecato, e quindi che sarà bene mettere da parte nelle nostre abitudini di programmazione, almeno per chi non l'avesse già fatto. Queste funzionalità saranno rimosse probabilmente a partire dalla versione 8.0.
La funzione magica __autoload()
è stata sostituita da spl_autoload_register()
già dalla versione 5.1 e il suo utilizzo è stato scoraggiato dalla documentazione. Il principale vantaggio di spl_autoload_register()
è la capacità di fornire autoloaders concatenati, facilitando così l'interoperabilità della libreria. Da ricordare che i due costruttu si escludono reciprocamente e quindi non possono convivere.
Se in php.ini abbiamo abilitato la funzione track_errors
, viene generato un errore che non blocca l'esecuzione del codice e nemmeno viene intercettato da un gestore di errori, viene allora, o meglio veniva, catturato dalla variabile $php_errormsg
. Dalla versione di PHP 7.2 sarà opportuno utilizzare per questo scopo la funzione error_get_last()
per recuperare l'ultimo errore generato.
Prima dell'introduzione delle closures
in PHP 5.3 era possibile creare delle funzioni usando create_functions()
, passando il nome della funzione e il corpo come stringa. Oramai non ha senso usare questa funzione che, oltretutto, potrebbe introdurre problematiche di sicurezza.
Deprecata anche l'impostazione di php.ini
mbstring.func_overload
che permetteva la sovrascrittura di alcune funzioni per la manipolazione delle stringhe con altre definite nell'estensione mbstring
; ciò rendeva questa impostazione incompatibile con il resto del codice. La raccomandazione è di utilizzare direttamente le funzioni mb_*
.
Altra funzione deprecata sarà (unset)
cast che restituisce un valore null
. Ciò significa che (unset) expr
è semplicemente un'espressione che restituisce sempre null
. Oltre ad essere inutile, questo comportamento è anche confuso, poiché molti programmatori pensano che (unset) $variabile
si comporterà in modo simile a unset($a)
, cosa non vera.
Non sarà poi possibile usare parse_str()
senza il secondo argomento, come già raccomandato del resto dalla documentazione ufficiale. D'altra parte l'accesso diretto alla variabile in questo caso non è altro che una sopravvivenza dei vecchi codici basati sulla logica dei register_globals, l'esigenza di abbandonare questa tecnica di programmazione, anche in questo caso, è legata a ragioni di sicurezza.
La funzione gmp_random()
è deprecata a favore di gmp_random_bits()
e di gmp_random_range()
che non sono legate a dipendenza da piattaforma come la prima.
Viene deprecata anche la funzione each()
a vantaggio della sua analoga foreach()
, per meglio dire, analoga nel comportamento ma dieci volte più veloce.
La funzione assert()
ha due modalità di funzionamento: se viene passato qualcosa di diverso da una stringa, ci dice che il valore è truthy
. Invece se viene passata una stringa, verrà eseguita tramite eval()
e l'assert verifica che il risultato dell'eval()
sia truthy
. La spiegazione di ciò risiede nel fatto che prima di PHP 7 questo è stato l'unico modo per evitare che l'espressione di affermazione venisse valutata. A partire da PHP 7, l'opzione zend.assertions
nel php.ini
può essere utilizzata per evitare la valutazione delle espressioni di asserzione.
Infine viene deprecato l'uso $errorcontext
per avere il riferimento ai gestori degli errori, si consiglia di usare debug_backtrace()
o meglio ancora un debugger.