Lançado!
PHP 8.1 é uma atualização importante da linguagem PHP.
Ela contem muitas funcionalidades novas, incluindo enums, propriedades somente leitura, sintaxe de chamáveis de primeira classe, fibras, tipos de interseção, melhorias de performance e mais.

Enumerações RFC Doc

PHP < 8.1
class Status
{
const
DRAFT = 'draft';
const
PUBLISHED = 'published';
const
ARCHIVED = 'archived';
}
function
acceptStatus(string $status) {...}
PHP 8.1
enum Status
{
case
Draft;
case
Published;
case
Archived;
}
function
acceptStatus(Status $status) {...}
Use enum em vez de um conjunto de constantes e obtenha validação de forma transparente.

Propriedades Somente Leitura RFC Doc

PHP < 8.1
class BlogData
{
private
Status $status;

public function
__construct(Status $status)
{
$this->status = $status;
}

public function
getStatus(): Status
{
return
$this->status;
}
}
PHP 8.1
class BlogData
{
public readonly
Status $status;

public function
__construct(Status $status)
{
$this->status = $status;
}
}

Propriedades somente leitura não podem ser alteradas após a inicialização, ou seja, após um valor ser atribuido a elas.
Elas são uma ótima maneira de modelar objetos de valor (Value Objects) e objetos de transferência de dados (DTO).

Sintaxe de Callabes de Primeira Classe RFC Doc

PHP < 8.1
$foo = [$this, 'foo'];

$fn = Closure::fromCallable('strlen');
PHP 8.1
$foo = $this->foo(...);

$fn = strlen(...);

Agora é possível obter a referência de qualquer função – isso é chamado de sintaxe de callable de primeira classe.

New em inicializadores RFC

PHP < 8.1
class Service
{
private
Logger $logger;

public function
__construct(
?
Logger $logger = null,
) {
$this->logger = $logger ?? new NullLogger();
}
}
PHP 8.1
class Service
{
private
Logger $logger;

public function
__construct(
Logger $logger = new NullLogger(),
) {
$this->logger = $logger;
}
}

Objetos agora podem ser usados como valor padrão de parâmetros, variáveis estáticas, e constantes globais, bem como em argumentos de atributos.

Isso efetivamente torna possível usar atributos aninhados.

PHP < 8.1
class User
{
/**
* @Assert\All({
* @Assert\NotNull,
* @Assert\Length(min=5)
* })
*/
public string $name = '';
}
PHP 8.1
class User
{
#[
\Assert\All(
new
\Assert\NotNull,
new
\Assert\Length(min: 5))
]
public
string $name = '';
}

Tipos de Interseção Puros RFC Doc

PHP < 8.1
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);
}
PHP 8.1
function count_and_iterate(Iterator&Countable $value) {
foreach (
$value as $val) {
echo
$val;
}

count($value);
}

Use tipos de interseção quando um valor precisa satisfazer múltiplas restrições de tipo ao mesmo tempo.

Atualmente não é possível misturar tipos de interseção e união como A&B|C.

Tipo de retorno never RFC Doc

PHP < 8.1
function redirect(string $uri) {
header('Location: ' . $uri);
exit();
}

function
redirectToLoginPage() {
redirect('/login');
echo
'Hello'; // <- dead code
}
PHP 8.1
function redirect(string $uri): never {
header('Location: ' . $uri);
exit();
}

function
redirectToLoginPage(): never {
redirect('/login');
echo
'Hello'; // <- dead code detected by static analysis
}

Uma função ou método declarada com o tipo never indica que ela não irá retornar um valor e irá lançar uma exceção ou terminar a execução do script com uma chamada de die(), exit(), trigger_error(), ou algo similar.

Constantes de classe finais RFC Doc

PHP < 8.1
class Foo
{
public const
XX = "foo";
}

class
Bar extends Foo
{
public const
XX = "bar"; // No error
}
PHP 8.1
class Foo
{
final public const
XX = "foo";
}

class
Bar extends Foo
{
public const
XX = "bar"; // Fatal error
}

É possível declarar constantes de classe como final, de forma que elas não possam ser sobrescritas em classes filhas.

Notação explícita de numeral octal RFC Doc

PHP < 8.1
016 === 16; // false because `016` is octal for `14` and it's confusing
016 === 14; // true
PHP 8.1
0o16 === 16; // false — not confusing with explicit notation
0o16 === 14; // true

Agora é possível escrever números octais com o prefixo explícito 0o.

Fibras RFC Doc

PHP < 8.1
$httpClient->request('https://example.com/')
->
then(function (Response $response) {
return
$response->getBody()->buffer();
})
->
then(function (string $responseBody) {
print
json_decode($responseBody)['code'];
});
PHP 8.1
$response = $httpClient->request('https://example.com/');
print
json_decode($response->getBody()->buffer())['code'];

Fibras são primitivos para implementar concorrência cooperativa leve. Elas são meios de criar blocos de código que podem ser pausados e retomados como Geradores, mas de qualquer lugar da pilha de execução. Fibras em si não fornecem concorrência magicamente, um laço de eventos ainda é necessário. No entanto, elas permitem que implementações bloqueantes e não bloqueantes compartilhem a mesma API.

Fibras permitem livrar-se de código boilerplate visto anteriormente com Promise::then() ou corrotinas baseadas em Geradores. Bibliotecas geralmente constróem abstrações adicionais em torno das Fibras, então não há necessidade de interagir com elas diretamente.

Suporte a desempacotamento de array para arrays com chaves string RFC Doc

PHP < 8.1
$arrayA = ['a' => 1];
$arrayB = ['b' => 2];

$result = array_merge(['a' => 0], $arrayA, $arrayB);

// ['a' => 1, 'b' => 2]
PHP 8.1
$arrayA = ['a' => 1];
$arrayB = ['b' => 2];

$result = ['a' => 0, ...$arrayA, ...$arrayB];

// ['a' => 1, 'b' => 2]

PHP já suportava o desempacotamento dentro de arrays através do operador de espalhamento, mas somente se o array tivesse chaves de inteiro. Agora também é possível desempacotar arrays com chaves string.

Melhorias de Performance

Tempo de requisição do App Demo Symfony
25 execuções consecutivas, 250 requisições (sec)
(menos é melhor)

O resultado (relativo ao PHP 8.0):

  • 23.0% mais rápido no Demo Symfony
  • 3.5% mais rápido no WordPress

Funcionalidades relacionadas a performance no PHP 8.1:

  • Backend JIT para ARM64 (AArch64)
  • Cache de herança (evita religamento de classes em cada requisição)
  • Resolução rápida de nome de classe (evita conversão em minúsculas e busca via hash)
  • Melhorias de performance na timelib e ext/date
  • Melhorias em iteradores de sistema de arquivo SPL
  • Otimizações em serialize/unserialize
  • Otimização de algumas funções internas (get_declared_classes(), explode(), strtr(), strnatcmp(), dechex())
  • Melhorias e correções no JIT

Novas Classes, Interfaces e Funções

  • Novo atributo #[ReturnTypeWillChange].
  • Novas funções fsync e fdatasync.
  • Nova função array_is_list.
  • Novas funções Sodium XChaCha20.

Alterações obsoletas e incompatibilidades com versões anteriores

  • Passagem de null para parâmetros não anuláveis em funções internas está depreciada.
  • Tipos de retorno provisórios em métodos de classes embutidas do PHP.
  • Interface Serializable depreciada.
  • Funções de de/codificação de entidades HTML processam aspas simples e as substituem por padrão.
  • Restrições da variável $GLOBALS.
  • MySQLi: Modo de erro padrão definido para exceções.
  • Conversão implícita incompatível de float para int está depreciada.
  • Extenção finfo: Recursos file_info migrados para objetos finfo existentes.
  • IMAP: Recursos imap migrados para objetos da classe IMAP\Connection.
  • Extensão FTP: Recursos de conexão migrados para objetos da classe FTP\Connection.
  • Extensão GD: Identificadores de fonte migrados para objetos da classe GdFont.
  • LDAP: Recursos migrados para objetos LDAP\Connection, LDAP\Result, e LDAP\ResultEntry.
  • PostgreSQL: Recursos migrados para PgSql\Connection, PgSql\Result, e PgSql\Lob objects.
  • Pspell: Recursos de dicionário e configuração migrados para objetos de classe PSpell\Dictionary e PSpell\Config.
To Top