É hora de uma nova versão do PHP, a linguagem de script do lado do servidor que alimenta nosso CMS favorito, o WordPress. Antes do lançamento da versão 8.4, em 21 de novembro, os desenvolvedores do PHP revelaram várias versões iniciais da nova base de código, incluindo vários candidatos a lançamento desde o congelamento de novos recursos em agosto.

Juntamente com os novos recursos, melhorias e depreciações, antecipamos que nesta época do ano, 2024 trouxe ajustes ao ciclo de lançamento do PHP, com o fim das atualizações de segurança para todas as versões atualmente suportadas sincronizado com o final do ano, em vez de coincidir com a data de lançamento GA.

Além disso, esse suporte foi estendido por um ano, o que significa que você poderia estar usando o PHP 8.4 com segurança até 2028 (com dois anos de segurança e correções de bugs e dois anos apenas de correções de segurança).

Embora você possa ter mais tempo para aproveitar o PHP 8.4, provavelmente está curioso para saber o que há de novo nesta versão. Então, vamos direto ao assunto.

Novos recursos e melhorias no PHP 8.4

Os novos recursos incluídos no lançamento do PHP 8.3 no ano passado parecerão discretos quando comparados a algumas das adições encontradas no 8.4:

Hooks de propriedade

Os hooks de propriedade trazem uma abordagem totalmente nova para lidar com “getters” e “setters” na programação orientada a objetos (OOP) do PHP, permitindo que você simplifique a estrutura dos seus arquivos de classe.

Como exemplo do que os hooks de propriedade podem substituir, a classe simples abaixo inclui as propriedades $size e $flavor. Elas têm visibilidade private para protegê-las do acesso direto fora do objeto resultante. É por isso que os métodos públicos getter e setter mediam o acesso às propriedades:

class Coffee
{
    private string $size;
    private string $flavor;
    public function __construct(string $size, string $flavor) {
        $this->size   = $size;
        $this->flavor = $flavor;
    }

    // "Setting" coffee size and flavor
    public function setSize(string $size): void {
        $this->size = $size;
    }
    public function setFlavor(string $flavor): void {
        $this->flavor = $flavor;
    }

    // "Getting" coffee size and flavor
    public function getSize(): string {
        return $this->size;
    }
    public function getFlavor(): string {
        return $this->flavor;
    }
} // End of class

// Make some coffee
$coffee = new Coffee('Small', 'Pumpkin Spice');
print $coffee->getSize() . ' ' . $coffee->getFlavor(); // Prints "Small Pumpkin Spice"

// Change order
$coffee->setSize('Grande');
$coffee->setFlavor('Mocha');
print $coffee->getSize() . ' ' . $coffee->getFlavor(); // Prints "Grande Mocha"

Ou, talvez sua classe tenha muitas propriedades e, em vez de escrever muitos métodos getter e setter, você use os métodos mágicos do PHP _get e _set. Você pode até organizar as coisas com uma estrutura switch um tanto bagunçada, como no trecho abaixo.

// __set magic method example
public function __set(string $key, $value): void 
    switch ($key) {
        case 'size':
            $this->size = $value;
            break;
        case 'flavor':
            $this->flavor = $value;
            break;
        default:
            throw new InvalidArgumentException('Invalid input');
        }
}

// Later, we can change the coffee order like this:
$coffee->size = 'Grande';
$coffee->flavor = 'Mocha';

Seja qual for a abordagem escolhida, quanto mais propriedades você tiver em sua classe, mais distante o código usado para manipulá-las ficará das definições localizadas no início do arquivo de classe. Além disso, algumas implementações dos métodos mágicos _get e _set podem fornecer inesperadamente acesso a propriedades privadas ou protegidas em seu objeto que você não pretendia expor.

O novo recurso de hooks de propriedade agrupa a funcionalidade getter e setter com as próprias propriedades. No exemplo de hooks de propriedade abaixo, você notará que as propriedades $size e $flavor da classe Coffee agora são públicas. Mas também adicionamos alguma validação básica aos hooks set, diferenciando-os das atribuições diretas.

// Property definitions at the top of our Coffee class
class Coffee
{
    public string $flavor {
        set(string $value) {
            if (strlen($value) > 16) throw new InvalidArgumentException('Input is too long');
                $this->flavor = $value;
        }
    }

    public string $size {
        set(string $value) {
            if (! in_array($value, array(‘Small’, ‘Grande’))) throw new InvalidArgumentException('Not a valid size');
                $this->size = $value;
        }
    }

    // Rest of the Coffee class
}

// Define a coffee
$coffee = new Coffee();
$coffee->size = 'Grande';
$coffee->flavor = 'Pumpkin spice';

Da mesma forma, como você pode ver abaixo, um hook get pode incluir funcionalidades no que parece ser uma referência comum a uma propriedade de objeto.

// Simplified Coffee class
class Coffee
{
    public string $flavor {
        get { 
            return $this->flavor . ' Spice';
       }
    }
}

// Create a flavor 
$coffee = new Coffee();
$coffee->flavor = 'Pumpkin'; // Stores the value "Pumpkin"
print $coffee->flavor;       // Prints "Pumpkin Spice"

Ao contrário dos métodos mágicos do PHP, os hooks de propriedade podem ser usados em interfaces e classes abstratas. Um exemplo de interface:

interface Coffee
{
    public string $size { get; set; }
    public string $flavor { get; set; }
}

Visibilidade assimétrica

Os métodos getter e setter publicamente visíveis que vimos anteriormente representam a abordagem tradicional de acesso a propriedades privadas e protegidas em suas classes.

Um recurso interessante do PHP 8.4 é a capacidade de uma propriedade ter diferentes níveis de visibilidade, dependendo do contexto em que é acessada. Portanto, uma propriedade pode ser pública quando estiver sendo lida, mas privada ou protegida quando estiver sendo definida.

Dê uma olhada nisso:

class Coffee
{
    public private(set) string $flavor = 'Pumpkin Spice';
}

$coffee = new Coffee();
print $coffee->flavor;     // Prints "Pumpkin Spice"
$coffee->flavor = 'Mocha';  // Error (visibility)

Acima, a propriedade $flavor da classe é pública, exceto em um contexto de configuração. Isso já é bastante simples, mas a visibilidade assimétrica tem até mesmo um atalho:

class Coffee
{
    // public is assumed when the context is not setting
    private(set) string $flavor = 'Pumpkin Spice';
}

Você pode usar hooks de propriedade e visibilidade assimétrica em combinação para obter uma enorme flexibilidade no trabalho com propriedades de objetos de várias visibilidades.

Uso de new em cadeia sem parênteses

Por falar em atalhos, chamar new e encadear métodos costumava exigir que fosse envolvida por parênteses, assim:

$coffee = (new Coffee())->getFlavor()->getSize();

O PHP 8.4 permite isso:

$coffee = new Coffee()->getFlavor()->getSize();

Pode parecer uma mudança pequena, mas o fato de você eliminar apenas dois parênteses facilita muito a leitura e a depuração.

Novas funções para localizar itens em array

Do departamento “Como assim, não podíamos fazer isso antes?”, o PHP 8.4 apresenta a função array_find(), que pode pesquisar elementos em um array para membros que correspondam às condições expressas em uma função de callback. A função retorna o valor do primeiro elemento que corresponde ao teste do callback.

A nova versão inclui três outras funções relacionadas:

  • array_find_key(): Como array_find(), mas o valor retornado é a chave do elemento correspondente em vez do valor do próprio elemento.
  • array_all(): Retorna true se todos os elementos da array que está sendo testada corresponderem ao teste do callback.
  • array_any(): Retorna true se pelo menos um dos elementos do array corresponder ao teste do callback.

Observe que as duas últimas funções retornam indicadores booleanos em vez de chaves ou conteúdo do array.

Aqui estão alguns exemplos rápidos:

$array = [
    'a' => 'Mocha',
    'b' => 'Caramel',
    'c' => 'Maple',
    'd' => 'Pumpkin'
   ];

// Find the first flavor name that is 5 characters long
var_dump(array_find($array, function (string $value) {
    return strlen($value) == 5;
})); // Returns “Mocha,” even though “Maple” is the same length 

// Find the array key for the first flavor with a name longer than 5 characters.
var_dump(array_find_key($array, function (string $value) {
    return strlen($value) > 5;
})); // Returns “b”

// Check to see if any flavor name is less than 5 characters long
var_dump(array_any($array, function (string $value) {
    return strlen($value) < 5;
})); // Returns false

// Check to see if all flavor names are shorter than 8 characters
var_dump(array_all($array, function (string $value) {
    return strlen($value) < 8;
})); // Returns true

Análise de HTML5

O HTM5 é o padrão de fato para a estrutura das páginas web modernas, mas a tecnologia de análise do DOM (Document Object Model) do PHP parou no HTML 4.01.

Em vez de atualizar a classe DOMDocument existente que funciona com os padrões HTML mais antigos, o PHP 8.4 vem com uma nova classe DomHTMLDocument que está pronta para o HTM5.

Você pode importar o conteúdo de uma página HTML5 desta forma:

$document = DomHTMLDocument::createFromString($html)

Além do construtor createFromString($html) acima, a classe também suporta createFromFile($path) e createEmpty()

O novo analisador reconhece tags HTML5 semânticas como main, article e section, que agora são familiares para a maioria de nós.

Funções de trim com suporte a multibyte

Outra adição no PHP 8.4 que parece ter demorado a chegar é o suporte a multibyte nas funções trim:

  • mb_trim()
  • mb_ltrim()
  • mb_rtrim()

Como a função de longa data do PHP trim(), mb_trim remove o espaço em branco e alguns caracteres especiais, como avanços de linha, de ambas as extremidades de uma string que pode conter caracteres multibyte. As outras funções cortam as extremidades esquerda ou direita de uma string.

Depreciações no PHP 8.4

Cada versão do PHP traz consigo uma lista de recursos e funções (alguns bastante obscuros) que são sinalizados para eventual remoção da plataforma. Uma depreciação de maior destaque no PHP 8.4 é o rastreamento de sessão sem cookies.

Depreciação de sessões via GET/POST

Embora os cookies sejam, em geral, o método preferido para rastrear sessões de usuários, o PHP suporta a fixação de dados de ID de sessão em parâmetros GET/POST. Para ativar o rastreamento de sessão por meio de parâmetros em URLs, a configuração do PHP session.use_only_cookies está desativada e a configuração session.use_trans_sid pode ser ativada.

Com o PHP 8.4, qualquer um desses estados para as configurações acionará um aviso de depreciação que pode aparecer nos registros do seu site. Quando o PHP 9 for lançado, essas configurações não estarão mais disponíveis.

Outras depreciações (e remoções) no PHP 8.4

Abaixo você encontra uma lista de funcionalidades que foram descontinuadas pela equipe por trás do PHP 8.4. (Algumas incluem links para mais informações sobre esses recursos.)

  • Formalmente depreciadas as propriedades DOMDocument e DOMEntity.
  • Remoção de DOMImplementation::getFeature($feature, $version).
  • Depreciação da constante DOM_PHP_ERR.
  • Depreciação da tag “S” em unserialize().
  • Depreciação de session.sid_length e session.sid_bits_per_character.
  • Depreciação de SplFixedArray::__wakeup().
  • Depreciação de xml_set_object() e xml_set_*_handler() com nomes de métodos de string.
  • Depreciação da passagem de null e false para dba_key_split().
  • Depreciação da passagem de tipos de dados incorretos para opções em funções da extensão ext/hash.
  • Depreciação das constantes SUNFUNCS_RET_STRING, SUNFUNCS_RET_DOUBLE, SUNFUNCS_RET_TIMESTAMP.
  • Depreciação do mecanismo proprietário de escape de CSV.
  • Depreciação da constante E_STRICT.
  • Depreciação de strtok().
  • Depreciação de retornar valores não string de um manipulador de saída personalizado.
  • Depreciação de produzir saída em um manipulador de saída personalizado.
  • Depreciação de file_put_contents() com $data como uma matriz.
  • Depreciação de mysqli_ping() e mysqli::ping()
  • Depreciação de mysqli_refresh().
  • Depreciação de mysqli_kill().
  • Depreciação do segundo parâmetro para mysqli_store_result().
  • Depreciação de lcg_value().
  • Depreciação de uniqid().
  • Depreciação de md5(), sha1(), md5_file(), e sha1_file().
  • Depreciação de passarE_USER_ERROR para trigger_error().
  • Depreciação do uso de um único sublinhado (“_”) como nome de classe.
  • Depreciação da constante SOAP_FUNCTIONS_ALL e passá-la para SoapServer::addFunction().

Resumo

O PHP 8.4 vem com algumas mudanças interessantes. Estamos ansiosos para colocar essa versão em nossos servidores em breve para nosso benchmarking anual do PHP – nossos testes com vários sistemas de gerenciamento de conteúdo baseados em PHP.

Também estamos curiosos em ver quando os desenvolvedores começarão a incorporar alguns dos novos recursos do PHP 8.4 em seus projetos, especialmente os hooks de propriedade.

Quais recursos do PHP 8.4 são os seus favoritos? Compartilhe suas opiniões com nossa comunidade nos comentários!

Steve Bonisteel Kinsta

Steve Bonisteel é um Editor Técnico na Kinsta que começou sua carreira de escritor como jornalista impresso, cobrindo ambulâncias e caminhões de bombeiros. Ele tem coberto tecnologia relacionada à Internet desde o final dos anos 1990.