Explorando as novidades do PHP 8.1: Recursos e Melhorias

Explorando as novidades do PHP 8.1: Recursos e Melhorias

O PHP (Hypertext Preprocessor) foi lançado pela primeira vez em junho de 1995 por Rasmus Lerdorf. Em setembro de 2023, foram cumpridos 28 anos desde o lançamento oficial do PHP. Essa versão inicial foi amplamente utilizada para criar páginas da web dinâmicas.

Por ser uma linguagem de código aberto, desde então, muitas novas versões e lançamentos foram disponibilizados com a contribuição de desenvolvedores de todo o mundo.

A comunidade de desenvolvedores que mantém o PHP em constante evolução anunciou, em 25 de novembro de 2021, a tão esperada versão do PHP 8.1.

Nessa nova versão, foram adicionados novos recursos e melhorias, que serão apresentados e detalhados ao longo deste artigo.

Aqueles que estão atualizados com as versões mais recentes sabem que a versão 8.2 foi lançada em 8 de dezembro de 2022 (e a versão 8.3 está atualmente em fase de testes). Em breve, farei um artigo específico para a versão 8.2.

Espero que este artigo o ajude a ficar por dentro dos novos recursos e melhorias do PHP 8.1.

Tenha uma ótima leitura.


Novos recursos

Tipo Enum

Sem dúvida, esse novo tipo de variável era uma das novidades mais aguardadas pelos desenvolvedores.

A funcionalidade Enum foi introduzida no PHP 8.1 como uma maneira de definir e trabalhar com enumeradores, que são uma estrutura de dados especial capaz de representar um conjunto fixo de valores nomeados. Enumeradores são muito úteis quando você precisa criar um conjunto limitado de opções que podem ser utilizadas em seu código.

Esse novo tipo é de grande importância, pois torna o código-fonte mais legível e fácil de manter.

Sintaxe do novo tipo Enum

Em versões anteriores ao PHP 8.1, para trabalhar com a estrutura parecida com Enums, era preciso criar uma classe como abaixo:

class Status
{
    const DRAFT     = 'draft';
    const PUBLISHED = 'published';
    const ARCHIVED  = 'archived';
}
function acceptStatus(string $status) {...}


Com a classe acima, definimos três possíveis status para uma postagem em um blog, por exemplo.

Para fazer o mesmo e definir uma Enum do php 8.1, você precisa do trecho de código como segue:

enum Status
{
    case Draft;
    case Published;
    case Archived;
}
function acceptStatus(Status $status) {...}


O código fica menor e mais fácil de manter, além de torná-lo mais simples.

Para utilizar essa enum é fácil, você pode incluir como um tipo em um atributo de outra classe:

class Post
{

    public Status $status;

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

    public function getStatus(): Status {
        return $this->status;
    }
}

Essa é uma funcionalidade pois permite que a estrutura do código fonte fique mais fácil de manter e de entender.

Read-only properties

Essa é uma adição significativa à linguagem que permite que você defina propriedades de classe como somente leitura.

Isso significa que uma vez que uma propriedade somente leitura é atribuída a um valor no construtor da classe, ela não pode mais ser modificada ou atribuída em nenhum outro lugar no código da classe.

Isso promove a imutabilidade e ajuda a garantir a integridade dos dados em objetos.

Abaixo um exemplo de como você pode utilizar essa nova funcionalidade:

class Person {
    public readonly string $name;
    public readonly int $age;

    public function __construct(string $name, int $age) {
        $this->name = $name;
        $this->age = $age;
    }
}


Dessa forma, ao instanciar um objeto passando o nome e a idade, não será mais possível, em tempo de execução, alterar essas duas propriedades, o que traz mais integridade ao código.

Pode ser mais fácil entender essa nova funcionalidade quando temos uma classe com parâmetros de sistema que não devem ser alterados em nenhuma situação, por exemplo, urls de api, ids de api e etc.

É uma ótima funcionalidade que traz mais segurança para o código fonte.

Sintaxe First-class Callable

A "sintaxe de callable de primeira classe" é uma nova funcionalidade introduzida na nova versão que torna mais fácil e legível o tratamento de funções e métodos como valores (callable) em seu código.

Isso é útil em situações em que você deseja passar funções como argumentos para outras funções, armazenar funções em variáveis ou retornar funções de outras funções.

Passando funções como argumentos

Antes do PHP 8.1, para passar uma função como argumento, você precisava passar o nome da função como uma string.

Agora, você pode usar a sintaxe de callable de primeira classe para tornar isso mais legível:

function process(callable $func, $data) {
    return $func($data);
}

// Uso
$resultado = process(fn($x) => $x * 2, 5);
echo $resultado; // Saída: 10


Armazenando Funções em Variáveis

Agora você pode armazenar funções em variáveis diretamente usando a sintaxe de callable de primeira classe:

$double = fn($x) => $x * 2;
echo $double(4); // Saída: 8


Retornando Funções de Outras Funções

Você também pode retornar funções de outras funções:

function multiplier($factor) {
    return fn($x) => $x * $factor;
}

$double = multiplier(2);
echo $double(5); // Saída: 10


A função multiplier retorna uma função que multiplica seu argumento pelo fator fornecido.

A sintaxe de callable de primeira classe torna o código mais limpo e legível ao trabalhar com funções como valores, tornando a manipulação de funções e métodos mais fácil e concisa no PHP 8.1 e versões posteriores.

New in initializers

A funcionalidade New in initializers foi introduzida na nova versão como uma nova característica que permite a criação de objetos diretamente no contexto de inicialização de propriedades de classe.

Antes do PHP 8.1, era necessário criar objetos em um construtor de classe ou em algum método.

Antes do PHP 8.1:

class Pessoa {
    private $nome;
    private $idade;

    public function __construct($nome, $idade) {
        $this->nome = $nome;
        $this->idade = $idade;
    }
}


No PHP 8.1, você pode fazer o seguinte:

class Pessoa {
    private $nome = 'John';
    private $idade = 30;
}


Isso é conveniente quando você deseja fornecer valores padrão ou iniciais para suas propriedades de classe.

Esta funcionalidade não se limita apenas a tipos escalares, mas também pode ser usada para criar objetos de classes personalizadas:

class Carro {
    private $modelo = new ModeloCarro();
    private $anoFabricacao = new Ano();
}


É importante observar que você não pode executar lógica complexa ou cálculos durante a inicialização de propriedades desta forma.

A criação de objetos é restrita a uma inicialização simples.

Pure Intersection Types

Essa é uma funcionalidade bacana que permite que uma variável em um método possa ser passada como uma variável Iterator e que possua um determinado tipo de dado dentro do array.

Por exemplo, digamos que você precisa iterar e realizar um count:

Antes do PHP 8.1 seria algo como abaixo:

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);
}


Com a nova funcionalidade pure intersection types:

function count_and_iterate(Iterator&Countable $value) {
    foreach ($value as $val) {
        echo $val;
    }

    count($value);
}


Aqui você define no parâmetro que a variável deve ser um Iterator com conteúdo do tipo Countable.

Never return type

Esse é um novo tipo de retorno de métodos que informa ao compilador que o método não irá retornar nada após a execução :

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

function redirectToLoginPage(): never {
    redirect('/login');
    echo 'Hello'; // <- código morto detectado por análise estática
}


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

Final class constants

Agora é possível declarar constantes como final na classe principal, assim, não será possível alterar a partir da classe filha.

class Foo
{
    final public const XX = "foo";
}

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


Essa funcionalidade traz mais segurança para o código.

Fibers

Fibers oferecem suporte à concorrência cooperativa no nível da linguagem.

Essa funcionalidade permite a criação de 'fibras' leves em seu código PHP.

As fibras são executadas concorrentemente, mas a execução entre elas é cooperativa, o que significa que as fibras devem voluntariamente ceder o controle para outras fibras em pontos específicos do código.

<?php

function taskA(Fiber $fiberB): Fiber {
    for ($i = 1; $i <= 5; $i++) {
        echo "Tarefa A - Iteração $i\n";
        Fiber::yield(); // Pausa a execução da Tarefa A e permite que a Tarefa B seja retomada
    }
    return $fiberB;
}

function taskB(): void {
    for ($i = 1; $i <= 5; $i++) {
        echo "Tarefa B - Iteração $i\n";
        Fiber::yield(); // Pausa a execução da Tarefa B e permite que a Tarefa A seja retomada
    }
}

$fiberA = new Fiber('taskA');
$fiberB = new Fiber('taskB');

while ($fiberA->isRunning() || $fiberB->isRunning()) {
    if ($fiberA->isRunning()) {
        $fiberA->resume($fiberB); // Retoma a Tarefa A e passa o controle para a Tarefa B
    }
   
    if ($fiberB->isRunning()) {
        $fiberB->resume(); // Retoma a Tarefa B
    }
}

echo "Concluído.\n";



No código acima, é possível perceber que, utilizando a classe Fiber, podemos instanciar duas threads passando o nome da função a ser executada e, assim, utilizar os helpers da classe Fiber para manipular e orquestrar sua execução.

Essa é uma boa forma de executar tarefas concorrentes que, em certo ponto, possuam dependências.

Array unpacking support for string-keyed arrays

Semelhante ao operador de rest do JavaScript, temos o operador '...' para realizar o unpacking de um array que possua suas chaves do tipo string (apenas para este caso).

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

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

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


Na versão anterior, era necessário utilizar o array_merge, mas nessa nova versão, foi adicionado o suporte para arrays com chaves do tipo string.

Depreciações e remoções

Aqui são listadas algumas das depreciações e funcionalidades removidas na versão 8.1 do PHP:

  1. Passar null para parâmetros de função interna não anuláveis está obsoleto.
  2. Tipos de retorno tentativos em métodos de classes internas do PHP.
  3. A interface serializable está obsoleta.
  4. Funções de en/decode de entidades HTML processam aspas simples e as substituem por padrão.
  5. Restrições na variável $GLOBALS.
  6. MySQLi: Modo de erro padrão definido como exceções.
  7. Conversão implícita incompatível de float para int está obsoleta.
  8. Extensão finfo: recursos de file_info migrados para objetos finfo existentes.
  9. IMAP: recursos imap migrados para objetos de classe IMAP\Connection.
  10. Extensão FTP: Recursos de conexão migrados para objetos de classe FTP\Connection.
  11. Extensão GD: Identificadores de fontes migrados para objetos de classe GdFont.
  12. LDAP: recursos migrados para objetos de classe LDAP\Connection, LDAP\Result e LDAP\ResultEntry.
  13. PostgreSQL: recursos migrados para objetos de classe PgSql\Connection, PgSql\Result e PgSql\Lob.
  14. Pspell: recursos pspell e pspell config migrados para objetos de classe PSpell\Dictionary e PSpell\Config.

Através do site da versão, você pode compreender melhor as depreciações e as remoções bem como ter acesso a documentação mais completa sobre as novas funcionalidades.

Link para o site da versão: https://www.php.net/releases/8.1/en.php


Conclusão

São 28 anos de desenvolvimento de uma linguagem sólida, mantida por colaboradores de todo o mundo e com utilização global.

A nova versão trouxe muitas funcionalidades esperadas por muitos desenvolvedores, além de melhorias significativas de desempenho.

As versões 8.2 e 8.3 também prometem trazer ótimas atualizações para a linguagem, que serão abordadas nos próximos artigos.

Como desenvolvedores, precisamos estar sempre atentos às atualizações de tecnologia. Saber exatamente como utilizar todos os recursos de uma linguagem pode te ajudar a ser muito mais produtivo e a escrever um código melhor.

Espero que tenham gostado, obrigado e até a próxima!

💡
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.