PHP7 – what’s new – I

Spread the love

Tipizzazione degli scalari

Facciamo una piccola introduzione. PHP è un linguaggio debolmente tipizzato, il che lo rende inviso a molti coders. Esso consente di fare cose strane del tipo

$a = '0';
$b = $a + 1; <---- questa è la cosa strana
$echo $b;
echo ':';
echo gettype($b)
// Output 1:integer

Ovvero l’operatore + (somma tra numeri interi/virgola mobile) è stato applicato ad una variabile $a che è string (che già è quanto meno esotico) e ad una costante che è integer per cui, a runtime, il compilatore ha deciso che il tipo del risultato $b andava conformato a quello della costante; prima di tutto ha effettuato il cast della stringa a intero ($a è “diventata” = 0, intero, non come stringa) e poi ha sommato la costante 1.

Alla fine il risultato è

// Output 1:integer

Effettivamente se non si fa attenzione a ciò che si scrive potremmo trovarci in situazioni inspiegabili e non abbiamo un compilatore che ci avverte (PHP è un linguaggio compilato ma la compilazione in bytecode viene fatta in modo silente dal motore Zend ogni volta che si lancia il programma dopo averlo modificato).

Nelle chiamate a funzione esiste la possibilità di forzare il tipo degli argomenti o in modo coattivo (coercive) oppure in modo stretto (strict).

Riprendiamo la funzione dell’articolo precedente e modifichiamo la lista dei parametri passati a runtime:

// 1.php - Coercive mode
function sumOfInts(int ...$ints) {
    return array_sum($ints);
}

var_dump(sumOfInts(2, '3', 4.1));

Possiamo specificare il tipo (un unico tipo per tutti i parametri) premettendolo ai tre puntini che precedono il nome dell’array; il tipo può essere SOLO uno dei seguenti:

  • int
  • string
  • float
  • bool

L’output di questo programma è

$ php 1.php 
/var/www/html/php7/1.php:10:
int(9)    

Nota che tutte le componenti dell’array sono state forzate a int, per cui 2+3+4=9. Questo comportamento è assunto per default, ovvero: in mancanza di indicazioni precise gli argomenti vengono forzati al tipo indicato.

Se si vuole che il blocco di codice invece utilizzi strettamente i tipi indicati, occorre istruire PHP attraverso una dichiarazione declare():

// Strict mode

declare(strict_types=1);

function sumOfInts(int ...$ints) {
    return array_sum($ints);
}

var_dump(sumOfInts(2, '3', 4.1));

l’output in questo caso evidenzia errori che riguardano solo l’errato tipo delle variabili in posizione 2 e 3:

PHP Fatal error:  Uncaught TypeError: Argument 2 passed to sumOfInts() must be of the type integer, string given, 
called in /var/www/html/php7/1.php on line 12 and defined in /var/www/html/php7/1.php:6
Stack trace:
#0 /var/www/html/php7/1.php(12): sumOfInts(2, '3', 4.1)
#1 {main}

Next TypeError: Argument 3 passed to sumOfInts() must be of the type integer, float given, 
called in /var/www/html/php7/1.php on line 12 and defined in /var/www/html/php7/1.php:6
Stack trace:
#0 /var/www/html/php7/1.php(12): sumOfInts(2, '3', 4.1)
#1 {main}
  thrown in /var/www/html/php7/1.php on line 6 

Se faccio girare questo script con una versione di PHP < 7 ho invece questo warning che riguarda la dichiarazione strict_types che è propria solo di PHP7:

[Tue Sep 25 11:43:12.440261 2018] [:error] [pid 4263] [client 127.0.0.1:52730] PHP Warning:  Unsupported declare 'strict_types' 
in /var/www/html/php7/1.php on line 3, referer: http://js/php7/

Tuttavia PHP 5.6 riconosce comunque l’impropria assegnazione di variabili non int a variabili dichiarate int e quindi fallisce:

[Tue Sep 25 11:43:12.441202 2018] [:error] [pid 4263] [client 127.0.0.1:52730] PHP Catchable fatal error:  Argument 1 
passed to sumOfInts() must be an instance of int, integer given, called in /var/www/html

Come si può vedere, c’è un sacco di roba che si può imparare dagli errori.

Diciamo senza malizia che l’effetto di PHP 7 in questo caso è di ammorbidire un già debole controllo sui tipi… Infatti se non imponiamo strict_types=1 lui fa una conversione al volo e fa funzionare un pezzo di codice che in PHP 5.6 non funzionerebbe! Tuttavia, se confrontiamo gli output di errore tra PHP 7 e PHP 5.6, vediamo che non si tratta più di un Catchable fatal error, ma di un errore di un nuovo tipo: TypeError (che vedremo nella prossima pillola).

Lascia un commento

Your email address will not be published.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.