class Status
{
const DRAFT = 'draft';
const PUBLISHED = 'published';
const ARCHIVED = 'archived';
}
function acceptStatus(string $status) {...}
enum Status
{
case Draft;
case Published;
case Archived;
}
function acceptStatus(Status $status) {...}
enum
en lugar de un conjunto de constantes y obtenga la validación lista para su uso. class BlogData
{
private Status $status;
public function __construct(Status $status)
{
$this->status = $status;
}
public function getStatus(): Status
{
return $this->status;
}
}
class BlogData
{
public readonly Status $status;
public function __construct(Status $status)
{
$this->status = $status;
}
}
Las propiedades de solo lectura no se pueden cambiar después de la inicialización, es decir, después de que se les asigne un valor. Son una excelente manera de modelar objetos de valor y objetos de transferencia de datos.
$foo = [$this, 'foo'];
$fn = Closure::fromCallable('strlen');
$foo = $this->foo(...);
$fn = strlen(...);
Ahora es posible obtener una referencia a cualquier función; esto se llama sintaxis First-class Callable.
class Service
{
private Logger $logger;
public function __construct(
?Logger $logger = null,
) {
$this->logger = $logger ?? new NullLogger();
}
}
class Service
{
private Logger $logger;
public function __construct(
Logger $logger = new NullLogger(),
) {
$this->logger = $logger;
}
}
Los objetos instanciados pueden ahora se utilizados como parámetros por defecto, así como variables estáticas, constantes globales, así como argumentos de atributos.
Esto efectivamente permite usar atributos anidados.
class User
{
/**
* @Assert\All({
* @Assert\NotNull,
* @Assert\Length(min=5)
* })
*/
public string $name = '';
}
class User
{
#[\Assert\All(
new \Assert\NotNull,
new \Assert\Length(min: 5))
]
public string $name = '';
}
function count_and_iterate(Iterator $value) {
if (!($value instanceof Countable)) {
throw new TypeError('value must be Countable');
}
foreach ($value as $val) {
echo $val;
}
count($value);
}
function count_and_iterate(Iterator&Countable $value) {
foreach ($value as $val) {
echo $val;
}
count($value);
}
Utilice tipos de intersección cuando un valor necesite resolver varias restricciones de tipado al mismo tiempo.
Actualmente no es posible mezclar tipos de intersección y unión como A&B|C
.
function redirect(string $uri) {
header('Location: ' . $uri);
exit();
}
function redirectToLoginPage() {
redirect('/login');
echo 'Hello'; // <- dead code
}
function redirect(string $uri): never {
header('Location: ' . $uri);
exit();
}
function redirectToLoginPage(): never {
redirect('/login');
echo 'Hello'; // <- dead code detected by static analysis
}
Una función o método declarado con el tipo never
indica que no devolverá un valor y producirá una excepción o finalizará la ejecución del script con una llamada de die()
, exit()
, trigger_error()
, o similar.
class Foo
{
public const XX = "foo";
}
class Bar extends Foo
{
public const XX = "bar"; // No error
}
class Foo
{
final public const XX = "foo";
}
class Bar extends Foo
{
public const XX = "bar"; // Fatal error
}
Es posible declarar la constante final
en la clase, para que no puedan ser sobreescrita en las clases heredadas.
016 === 16; // false because `016` is octal for `14` and it's confusing
016 === 14; // true
0o16 === 16; // false — not confusing with explicit notation
0o16 === 14; // true
Ahora es posible escribir números octales con el prefijo explícito 0o
.
$httpClient->request('https://example.com/')
->then(function (Response $response) {
return $response->getBody()->buffer();
})
->then(function (string $responseBody) {
print json_decode($responseBody)['code'];
});
$response = $httpClient->request('https://example.com/');
print json_decode($response->getBody()->buffer())['code'];
Fibers es la forma primitiva para la implementación ligera de concurrencia. Son un medio para crear bloques de código que se puedan pausarse y reanudarse como generadores (Generators), pero desde cualquier lugar de la pila. Los Fibers en sí mismo, no proporcionan la concurrecia mágicamente, todavía se necesita tener un bucle de eventos. Sin embargo, permiten que las implementaciones de bloqueo y no-bloqueo compartan la misma API.
Los Fibers permiten deshacerse del código repetitivo visto anteriormente con Promise::then()
o las corutinas basadas en el generador (Generator). Las bibliotecas generalmente construirán más abstracciones alrededor de Fibers, por lo que no hay necesidad de interactuar con ellas directamente.
$arrayA = ['a' => 1];
$arrayB = ['b' => 2];
$result = array_merge(['a' => 0], $arrayA, $arrayB);
// ['a' => 1, 'b' => 2]
$arrayA = ['a' => 1];
$arrayB = ['b' => 2];
$result = ['a' => 0, ...$arrayA, ...$arrayB];
// ['a' => 1, 'b' => 2]
PHP soportaba la desestructuración de Arrays, pero solo si el Array tenía keys de tipo integer. Ahora también es posible la desestructuración de Arrays con keys de tipo string.
#[ReturnTypeWillChange]
.fsync
y fdatasync
.array_is_list
.Serializable
es obsoleta.$GLOBALS
.file_info
migrado a objetos finfo existentes.IMAP\Connection
class objects.FTP\Connection
.GdFont
.LDAP\Connection
, LDAP\Result
, y LDAP\ResultEntry
.PgSql\Connection
, PgSql\Result
, y PgSql\Lob
.PSpell\Dictionary
, PSpell\Config
.