Ícone do site SOLOWEB Tecnologia

Novidade do PHP 8.3

O PHP 8.3 ainda não foi lançado oficialmente, mas sua versão alfa está disponível. De acordo com a lista de tarefas de preparação , o PHP 8.3 será lançado em 23 de novembro de 2023 . Ele será testado por meio de três lançamentos alfa, três beta e seis candidatos a lançamento.

O que há de novo no PHP 8.3: novos recursos e mudanças

json_validate()

Este PHP RFC propõe a introdução de uma nova função, json_validate(), para validar se uma string contém JSON válido.

As implementações atuais usam principalmente json_decode(), que gera um ZVAL (objeto/array/etc.) durante a análise e usa memória e poder de processamento desnecessários.

A nova função usa o mesmo analisador JSON que existe no núcleo do PHP e é usado pelo json_decode(), garantindo que o que é válido em json_validate() também seja válido em json_decode().

Aqui estão alguns exemplos de como usar json_validate():

No PHP 8.2 e anteriores, usando json_decode():

$json = '{ "foo": "bar" }';
 
$decoded = json_decode($json);
 
if ($decoded === null && json_last_error() !== JSON_ERROR_NONE) {
    // Invalid JSON.
} else {
    // Valid JSON.
}

No PHP 8.3, usando json_validate():

$json = '{ "foo": "bar" }';
 
if (json_validate($json)) {
    // Valid JSON.
} else {
    // Invalid JSON.
}

Saiba mais: PHP RFC: json_validate

Veja também

unserialize() – Tratamento de erros aprimorado

A RFC propõe duas mudanças principais na função unserialize do PHP para aprimorar seu tratamento de erros.

O tratamento de erro atual em unserialize() é inconsistente, pois pode emitir um E_NOTICE, um E_WARNING ou lançar um arbitrário ⁣, ou Exception Error dependendo de como a string de entrada está mal formada.

Isso dificulta o tratamento confiável de erros durante a desserialização.

A primeira proposta é introduzir uma nova exceção de wrapper, UnserializationFailedException.

Sempre que um Throwablefor lançado durante a unserialize, isso Throwableserá agrupado em uma nova instância de UnserializationFailedException.

Isso permite que os desenvolvedores usem um único catch(UnserializationFailedException $e) para lidar com todos Throwableos acontecimentos possíveis durante a desserialização.

O original Throwable pode ser acessado por meio da propriedade $previous de UnserializationFailedException, permitindo que o desenvolvedor aprenda sobre a causa real da falha de deserialização.

A segunda proposta é aumentar a severidade do reporte de erros no unserialize() parser.

No estado atual, a desserialização pode falhar devido a um erro de sintaxe na string de entrada, números inteiros fora do intervalo e problemas semelhantes, que resultam em um E_NOTICE ou E_WARNING.

Este RFC propõe aumentar a gravidade desses avisos/avisos e, finalmente, fazer com que eles lancem o novo arquivo UnserializationFailedException.

Antes das mudanças propostas, lidar com erros de desserialização em PHP poderia ser assim:

try {
    set_error_handler(static function ($severity, $message, $file, $line) {
        throw new \ErrorException($message, 0, $severity, $file, $line);
    });
    $result = unserialize($serialized);
} catch (\Throwable $e) {
    // Falha na deserialização. Bloco catch opcional se o erro não deve ser tratado.
} finally {
    restore_error_handler();
}
 
var_dump($result); // Faça algo com o $result.
                   // Não deve aparecer no 'tentar' para não 'capturar' erros não relacionados.

E vários casos típicos podem ser assim:

unserialize('foo'); // Notice: unserialize(): Error at offset 0 of 3 bytes in php-src/test.php on line 3
unserialize('i:12345678901234567890;'); // Warning: unserialize(): Numerical result out of range in php-src/test.php on line 4
unserialize('E:3:"foo";'); // Warning: unserialize(): Invalid enum name 'foo' (missing colon) in php-src/test.php on line 5
                           // Notice: unserialize(): Error at offset 0 of 10 bytes in php-src/test.php on line 5

Após as alterações propostas, o tratamento dos erros de deserialização no PHP ficaria da seguinte forma:

function unserialize(string $data, array $options = []): mixed
{
    try {
        // The existing unserialization logic happens here.
    } catch (\Throwable $e) {
        throw new \UnserializationFailedException(previous: $e);
    }
}

E a implementação da nova exceção:

class UnserializationFailedException extends \Exception
{
}

O RFC foi parcialmente aceito para PHP 8.3.

Saiba mais: PHP RFC: Melhore o tratamento de erros unserialize()

Adições de randomizador

O RFC para PHP intitulado “Randomizer Additions” propõe três novos métodos e uma enumeração de acompanhamento para a \Random\Randomizerclasse.

O método getBytesFromString() permite gerar uma string de um comprimento especificado usando bytes selecionados aleatoriamente de uma determinada string.

getFloat() método retorna um float entre um definido $min$max, com os limites do intervalo sendo abertos ou fechados dependendo do valor do parâmetro $boundary.

método nextFloat() é equivalente a ->getFloat(0, 1, \Random\IntervalBoundary::ClosedOpen).

A enumeração IntervalBoundaryé usada para determinar a natureza dos limites do intervalo no método getFloat()

Por exemplo, com o método getBytesFromString():

Antes:

$randomString = '';
 
$characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
 
$charactersLength = strlen($characters);
 
for ($i = 0; $i < 16; $i++) {
    $randomString .= $characters[rand(0, $charactersLength - 1)];
}
 
$randomDomain = $randomString . ".example.com";

Depois:

$randomizer = new \Random\Randomizer();
 
$randomDomain = $randomizer->getBytesFromString('abcdefghijklmnopqrstuvwxyz0123456789', 16) . ".example.com";

Saiba mais: PHP RFC: adições de randomizador

Busca constante de classe dinâmica

Este RFC propõe permitir que as constantes de classe sejam acessadas dinamicamente usando variáveis.

Em vez de acessar constantes de classe com um valor de string estático (por exemplo, ClassName::CONSTANT), você pode usar uma variável contendo o nome da constante.

$constant = 'CONSTANT';
 
ClassName::{$constant}

Essa alteração facilitaria o acesso às constantes de classe de forma dinâmica e programática.

Saiba mais: PHP RFC: busca constante de classe dinâmica

Exceções de data/hora mais apropriadas

A RFC propõe introduzir exceções e erros específicos de extensão de data/hora no PHP, em vez dos avisos, erros e exceções mais genéricos usados ​​atualmente.

Isso visa fornecer melhor especificidade e tratamento para exceções relacionadas a Data/Hora.

A proposta inclui várias exceções específicas, como DateInvalidTimeZoneExceptionDateInvalidOperationExceptionDateMalformedStringExceptionDateMalformedIntervalStringException, e outras.

Notavelmente, essa alteração afeta apenas o uso do estilo orientado a objeto de funções de data/hora, pois o uso do estilo procedural continuará a usar avisos e erros como atualmente.

Abaixo estão exemplos de como as novas exceções funcionam:

Antes da mudança:

Para criar um DateIntervalcom uma string mal formada, a chamada da função retornaria um aviso e falso:

try {
    $i = DateInterval::createFromDateString("foo");
} catch (Exception $e) {
    echo $e::class, ': ', $e->getMessage(), "\n";
}

Para tentar subtrair uma especificação de tempo relativo não especial de um DateTimeImmutableobjeto, a chamada de função retornaria um aviso e null:

$now = new DateTimeImmutable("2022-04-22 16:25:11 BST");
 
var_dump($now->sub($e));

Após a alteração:

Para criar um DateIntervalcom uma string mal formada, a função agora lança um DateMalformedIntervalStringException:

try {
    $i = DateInterval::createFromDateString("foo");
} catch (DateMalformedIntervalStringException $e) {
    echo $e::class, ': ', $e->getMessage(), "\n";
}

Para tentar subtrair uma especificação de tempo relativo não especial de um DateTimeImmutableobjeto, a função agora lança um DateInvalidOperationException:

$now = new DateTimeImmutable("2022-04-22 16:25:11 BST");
 
try {
    var_dump($now->sub($e));
} catch (DateInvalidOperationException $e) {
    echo $e::class, ': ', $e->getMessage(), "\n";
}

Saiba mais: PHP RFC: exceções de data/hora mais apropriadas

Leia apenas as alterações

Este é um RFC de duas partes e somente a parte em que as propriedades somente leitura podem agora ser reinicializadas durante a clonagem foi aceita.

Esta proposta visa eliminar a limitação que impede que propriedades readonly sejam “deep-cloned”.

Ele permite que as propriedades somente leitura sejam reinicializadas durante a execução da chamada do método mágico  __clone(). Aqui está um exemplo dessa mudança:

Antes:

class Foo {
    public function __construct(
        public readonly DateTime $bar,
        public readonly DateTime $baz
    ) {}
 
    public function __clone()
    {
        $this->bar = clone $this->bar; // Doesn't work, an error is thrown.
    }
}

Depois:

class Foo {
    public function __construct(
        public readonly DateTime $bar,
        public readonly DateTime $baz
    ) {}
 
    public function __clone()
    {
        $this->bar = clone $this->bar; // Works.
        $this->cloneBaz();
    }
 
    private function cloneBaz()
    {
        unset($this->baz); // Also works.
    }
}
 
$foo = new Foo(new DateTime(), new DateTime());
 
$foo2 = clone $foo;
// No error, Foo2::$bar is cloned deeply, while Foo2::$baz becomes uninitialized.

Saiba mais: PHP RFC: Alterações somente leitura

Saner array_sum() e array_product()

Este RFC introduz alterações no comportamento das funções array_sum()array_product() para torná-los mais consistentes com suas implementações de userland usando array_reduce().

Atualmente, array_sum()array_product() pula entradas de array ou objeto, enquanto suas implementações de userland usando array_reduce() lançam um arquivo TypeError.

As mudanças propostas incluem:

  1. Usando o mesmo comportamento para array_sum()array_product() como as array_reduce() variantes.
  2. Emitindo um E_WARNINGpara tipos incompatíveis.
  3. Objetos de suporte com elenco numérico para serem adicionados/multiplicados.

Saiba mais: PHP RFC: Saner array_(sum|product)()

PHP RFC: Constantes de classe digitadas

As constantes de classe digitadas estão finalmente chegando no PHP 8.3!

Eles ajudarão a reduzir erros e confusões decorrentes de classes filhas substituindo as constantes da classe pai.

As constantes de classe digitadas podem ser declaradas em classes, interfaces, características e enums.

Pontos chave:

Como você pode imaginar, as constantes digitadas são super fáceis de usar, assim como as propriedades tipadas:

interface Foo {
    public const string BAR = 'baz';
}
 
class Bar extends Foo {
    // Doesn't work anymore! You cannot change the
    // type and assign a value of another type.
    public const array BAR = ['foo', 'bar', 'baz'];
    // OK.
    public const string BAR = 'foo';
}

Saiba mais: PHP RFC: Constantes de classe digitadas

Inicializadores de variáveis ​​estáticas arbitrárias

A RFC propõe uma alteração que permitiria ao inicializador de variáveis ​​estáticas conter expressões arbitrárias, em vez de apenas expressões constantes.

Isso torna a linguagem mais flexível e menos confusa para os usuários. Por exemplo, antes dessa mudança, uma variável estática só podia ser inicializada com uma constante:

function foo() {
    static $i = 1;
    echo $i++, "\n";
}
 
foo();
foo();
foo();

Isso produziria:

1
2
3

Com a alteração proposta, uma variável estática pode ser inicializada com uma chamada de função:

function bar() {
    echo "bar() called\n";
    return 1;
}
 
function foo() {
    static $i = bar();
    echo $i++, "\n";
}
 
foo();
foo();
foo();

A proposta também introduz várias mudanças na semântica da inicialização de variáveis ​​estáticas, incluindo o tratamento de exceções durante a inicialização, a ordem das operações quando destruidores estão envolvidos e o tratamento da recursão durante a inicialização.

Porém, a declaração novamente de variáveis ​​estáticas não seria permitida e isso altera a forma como ReflectionFunction::getStaticVariables()funciona com variáveis ​​estáticas.

Saiba mais: PHP RFC: inicializadores de variáveis ​​estáticas arbitrárias

Sair da versão mobile