<?php
class foo { static $bar = 'baz'; }
var_dump('foo'::$bar);
?>
if < php7.0
then we will receive a syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)
but php7 returns string(3) "baz"
I think it's not documented anywhere
Le
dichiarazioni di tipi scalari
sono disponibili in due versioni: coercitivo (predefinito) e rigoroso. I seguenti tipi
per i parametri possono ora essere forzati (o coercitivo o rigoroso): stringhe
(string), interi (int
), numeri con virgola
mobile (float), e booleani (bool
). Questi
aumentano gli altri tipi introdotti in PHP 5: nomi delle classi, interfacce,
array e callable.
<?php
// Modalità coercitiva
function sumOfInts(int ...$ints)
{
return array_sum($ints);
}
var_dump(sumOfInts(2, '3', 4.1));
Il precedente esempio visualizzerà:
int(9)
Per abilitare la modalità rigorosa, una singola direttiva declare
deve essere posizionata
nella parte superiore del file. Questo significa che la severità della tipizzazione per i valori scalari è
configurata su una base per-file. Questa direttiva interessa non solo le dichiarazioni
di tipi di parametri, ma anche il tipo di ritorno di una funzione (vedere
dichiarazioni dei tipi di ritorno,
le funzioni interne di PHP, e le funzioni delle estensioni
caricate.
La documentazione completa e gli esempi sulle dichiarazioni dei tipi scalari si possono trovare nel riferimento dichiarazione del tipo.
PHP 7 aggiunge il supporto per le dichiarazioni del tipo di ritorno. Analogamente alle dichiarazioni dei tipi degli argomenti, le dichiarazioni del tipo di ritorno specificano il tipo del valore che sarà restituito da una funzione. Per le dichiarazioni del tipo di ritorno sono disponibili gli stessi tipi che sono disponibili per le dichiarazioni del tipo degli argomenti.
<?php
function arraysSum(array ...$arrays): array
{
return array_map(function(array $array): int {
return array_sum($array);
}, $arrays);
}
print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));
Il precedente esempio visualizzerà:
Array ( [0] => 6 [1] => 15 [2] => 24 )
La documentazione completa e gli esempi sulle dichiarazioni del tipo di ritorno si possono trovare nel riferimento le dichiarazioni del tipo di ritorno.
L'operatore null coalesce (??
) è stato aggiunto come
zucchero sintattico per il caso comune di dover utilizzare una ternaria in
congiunzione con isset(). Esso restituisce il suo primo operando
se esiste e non è null
; altrimenti restituisce il suo secondo operando.
<?php
// Legge il valore di $_GET['user'] e restituisce 'nobody'
// se esso non esiste.
$username = $_GET['user'] ?? 'nobody';
// Questo è equivalente a:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
// Più Coalesce possono essere incatenati: questo restituirà il primo
// valore definito tra $_GET['user'], $_POST['user'], e
// 'nobody'.
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
?>
L'operatore spaceship è usato per confrontare due espressioni. Restituisce -1, 0 o 1 quando $a è rispettivamente minore, uguale, o maggiore di $b. I confronti sono eseguiti secondo le consuete regole di confronto dei tipi di PHP.
<?php
// Interi
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// Numeri decimali
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// Stringhe
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
?>
Ora possono essere definiti Array costanti con
define(). In PHP 5.6, potevano essere definiti solo con
const
.
<?php
define('ANIMALS', [
'dog',
'cat',
'bird'
]);
echo ANIMALS[1]; // visualizza "cat"
?>
Il supporto per le classi anonime è stato aggiunto via new
class
. Queste possono essere usate al posto di definizioni di classi complete per
oggetti usa e getta:
<?php
interface Logger {
public function log(string $msg);
}
class Application {
private $logger;
public function getLogger(): Logger {
return $this->logger;
}
public function setLogger(Logger $logger) {
$this->logger = $logger;
}
}
$app = new Application;
$app->setLogger(new class implements Logger {
public function log(string $msg) {
echo $msg;
}
});
var_dump($app->getLogger());
?>
Il precedente esempio visualizzerà:
object(class@anonymous)#2 (0) { }
La documentazione completa può essere trovata nel riferimento delle classi anonime.
Questo ha come input un codepoint Unicode in una forma esadecimale, e restituisce quel codepoint in UTF-8 in una stringa con doppi apici oppure un heredoc. Qualsiasi codepoint valido è accettato, con gli iniziali 0 opzionali.
echo "\u{aa}";
echo "\u{0000aa}";
echo "\u{9999}";
Il precedente esempio visualizzerà:
ª ª (stesso di prima ma con gli iniziali 0 opzionali) 香
Closure::call() è un modo più performante e abbreviato di effettuare un binding temporaneo dello scope di un oggetto ad una closure e di invocarla.
<?php
class A {private $x = 1;}
// Codice prima di PHP 7
$getX = function() {return $this->x;};
$getXCB = $getX->bindTo(new A, 'A'); // closure intermedia
echo $getXCB();
// Codice PHP 7+
$getX = function() {return $this->x;};
echo $getX->call(new A);
Il precedente esempio visualizzerà:
1 1
Questa funzionalità cerca di fornire una miglior sicurezza quando si deserializzano oggetti su dati non attendibili. Previene possibili iniezioni di codice, consentendo agli sviluppatori di inserire nella whitelist le classi che possono essere deserializzate.
<?php
// converte tutti gli oggetti in oggetti __PHP_Incomplete_Class
$data = unserialize($foo, ["allowed_classes" => false]);
// converte tutti gli oggetti in oggetti __PHP_Incomplete_Class eccetto quelli di MyClass e MyClass2
$data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]]);
// comportamento predefinito (lo stesso che si ha omettendo il secondo argomento) che accetta tutte le classi
$data = unserialize($foo, ["allowed_classes" => true]);
La nuova classe IntlChar cerca di esporre funzionalità ICU addizionali. La classe stessa definisce un numero di metodi statici e costanti che possono essere usati per manipolare i caratteri unicode.
<?php
printf('%x', IntlChar::CODEPOINT_MAX);
echo IntlChar::charName('@');
var_dump(IntlChar::ispunct('!'));
Il precedente esempio visualizzerà:
10ffff COMMERCIAL AT bool(true)
Per poter utilizzare questa classe, l'estensione Intl deve essere installata.
Le aspetattive sono dei miglioramenti retrocompatibili alla vecchia funzione assert(). Permettono asserzioni a costo zero nel codice di produzione, e forniscono la possibilità di lanciare eccezioni personalizzate quando l'asserzione fallisce.
Mentre la vecchia API continua ad essere mantenuta per compatibilità, assert() è ora un costrutto del linguaggio, consentendo al primo parametro di essere un'espressione piuttosto che solo una string da essere valutata o un valore bool da essere testato.
<?php
ini_set('assert.exception', 1);
class CustomError extends AssertionError {}
assert(false, new CustomError('Qualche messaggio di errore'));
?>
Il precedente esempio visualizzerà:
Fatal error: Uncaught CustomError: Qualche messaggio di errore
Tutti i dettagli su questa funzione, incluso come configurarla sia in ambienti di sviluppo che di produzione, possono essere trovati nella sezione aspettative del riferimento assert().
use
Classi, funzioni e costanti importati dallo stesso namespace
possono ora essere raggruppati insieme in una singola istruzione use
.
<?php
// Codice prima di PHP 7
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;
use function some\namespace\fn_a;
use function some\namespace\fn_b;
use function some\namespace\fn_c;
use const some\namespace\ConstA;
use const some\namespace\ConstB;
use const some\namespace\ConstC;
// Codice PHP 7+
use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};
?>
Questa caratteristica si basa sulle funzionalità del generatore introdotte in PHP 5.5.
Si abilita per un'istruzione return
per essere usata all'interno di un
generatore per abilitare per una espressione final per essere restituita (il ritorno per
referenza non è permesso). Questo valore può essere preso usando il nuovo
metodo Generator::getReturn()
, che può solo essere usato
una volta che il generatore ha finito di effettuare lo yield dei valori.
<?php
$gen = (function() {
yield 1;
yield 2;
return 3;
})();
foreach ($gen as $val) {
echo $val, PHP_EOL;
}
echo $gen->getReturn(), PHP_EOL;
Il precedente esempio visualizzerà:
1 2 3
Essere in grado di restituire esplicitamente un valore final da un generatore è un'abilità comoda da avere. Questo perchè abilita per un valore final da essere restituito da un generatore (forse da qualche forma di routine di computazione) che può essere specificamente gestito dal codice client eseguendo il generatore. Questo è molto più semplice rispetto a forzare il codice del client a controllare prima che il valore final sia stato yieldato, e in quel caso, gestire il valore specificamente.
I generatori possono ora delegare ad un altro generatore,
oggetti Traversable o array
automaticamente, senza la necessita di scrivere boilerplate nel generatore
più esterno usando il costrutto yield from
.
<?php
function gen()
{
yield 1;
yield 2;
yield from gen2();
}
function gen2()
{
yield 3;
yield 4;
}
foreach (gen() as $val)
{
echo $val, PHP_EOL;
}
?>
Il precedente esempio visualizzerà:
1 2 3 4
La nuova funzione intdiv() esegue una divisione intera dei suoi operandi e la restituisce.
<?php
var_dump(intdiv(10, 3));
?>
Il precedente esempio visualizzerà:
int(3)
session_start() ora accetta un array di opzioni che sovrascrivono le direttive di configurazione della sessione normalmente impostate nel php.ini.
Queste opzioni sono state inoltre ampliate per supportare
session.lazy_write, che è
attivo di default e fa in modo che PHP possa solo sovrascrivere qualsiasi file di sessione se i
dati di sessione sono cambiati, e read_and_close
, che è
un'opzione che può solo essere passata a session_start() per
indicare che i dati di sessione dovrebbero essere letti e quindi che la sessione deve
essere immediatamente chiusa senza cambiamenti.
Per esempio, impostare
session.cache_limiter a
private
e chiudere immediatamente la sessione dopo averla
letta:
<?php
session_start([
'cache_limiter' => 'private',
'read_and_close' => true,
]);
?>
La nuova funzione preg_replace_callback_array() abilita il codice per essere scritto in maniera più pulita quando si usa la funzione preg_replace_callback(). Prima di PHP 7, le callback che avevano bisogno di essere eseguite per espressioni regolari richiedevano che la funzione di callback venisse sporcata con un sacco di ramificazione.
Ora, le callback possono essere registrate ad ogni espressione regolare usando un array associativo, dove la chiave è un'espressione regolare e il valore è una callback.
Due nuove funzioni sono state aggiunte per generare interi e stringhe crittograficamente sicuri in modo cross-platform: random_bytes() e random_int().
Precedentemente, non era garantito che list() operasse correttamente con gli oggetti che implementavano ArrayAccess. Questo è stato risolto.
(clone $foo)->bar()
.
<?php
class foo { static $bar = 'baz'; }
var_dump('foo'::$bar);
?>
if < php7.0
then we will receive a syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)
but php7 returns string(3) "baz"
I think it's not documented anywhere
A good rule of thumb for remembering what the spaceship operator expression returns is to replace the spaceship operator with a minus sign (-). If the result is negative, 0 or positive, the expression will return -1, 0 or 1 respectively.
Example:
<?php
echo 5 <=> 8; // 5 - 8 = -3, prints -1
echo 2 <=> 2; // 2 - 2 = 0, prints 0
echo 4 <=> 2; // 4 - 2 = 2, prints 1
In php 7.0 it's possible to curry functions in a way that's similar to JavaScript.
<?php
// A curried function
function add($a) {
return function($b) use ($a) {
return $a + $b;
};
}
// Invoking curried function in PHP 7
$result = add(10)(15);
var_dump($result); // int 25
?>
Currying in this way is not possible in php 5.6.
Be careful on performing null coalesce on typecasted properties. Enclose them in parenthesis
<?php
$foo = new StdClass;
//(int) 23
$bar = $foo->bas ?? 23;
var_dump($bar);
$foo = new StdClass;
//(int) 23
$bar = (int) ($foo->bas ?? 23);
var_dump($bar);
$foo = new StdClass;
$bar = (int) $foo->bas ?? 23;
//Notice: Undefined property: stdClass::$bas
var_dump($bar);
Currying was possible in php 5.6. But in php 7.0 it is now possible to invoke a curryied function with a one liner.
<?php
// A curried function
function add($a) {
return function($b) use ($a) {
return $a + $b;
};
}
// Invoking a curried function in PHP 7
$result = add(10)(15);
var_dump($result); // int 25
// Invoking a curried function in PHP 5.6
$add10 = add(10);
$result = $add10(15);
var_dump($result); // int 25
?>
$a = ''; // or 0 or false
$b = $a ?? 'a';
// $b is '' or 0 or false
$c = $a ?: 'a';
// $c is 'a'
It is worth nothing that the following code just works in PHP 7.4:
```
function nullOrDefault($x = null)
{
$x ??= 3222;
return $x;
}
```