O Andamento do PHP 8

Read in English

O PHP 8.0 está sob discussão e desenvolvimento neste momento. Isso significa que muitas coisas neste post ainda vão mudar muito com o tempo. Para cada área de interesse eu vou deixar um subtítulo e, conforme as conversas vão para frente na comunidade php, eu vou atualizar cada um de acordo.

Devo deixar claro que não serei capaz de atualizar este texto a cada atualização em tempo real, pois várias alterações acontecem todos os dias. Se você procura por uma lista atualizada por favor acompanhe o arquivo UPGRADE no repositório oficial.

Quando o PHP 8.0 será lançado?

A data de lançamento do PHP 8.0 é Dezembro de 2020. Ao menos esta é a data oficial até o momento.

O PHP 7.4 foi lançado há pouco tempo e não haverá nenhuma outra minor version (PHP 7.5) para esta major 7. Portanto a próxima versão será, com certeza, o PHP 8.


Funcionalidades aceitas para a versão 8.0

As funcionalidades listadas abaixo serão entregues com a versão 8.0. Elas já foram votadas, aceitas E implementadas.

Então se você quer ter um gostinho do que vem nesta versão, dá uma ligada nisso:

JIT: Just in Time Compiler

Claro que esta funcionalidade precisa de maior explicação e merece um post para si, escreverei em breve. Enquanto isso posso citar que esta funcionalidade diz ganhar performance até quatro vezes mais rápida no benchmark Mandelbrot.

Você pode ver a especificação e discussão visitando a RFC.

Union Types V2

A RFC Union Types V2 permitirá explicitar todos os possíveis tipos aceitos em vez do bom e velho mixed.

A nova sintaxe ficará como a seguinte:

function myFunction(int|float $number): int
{
  return round($number);
}

A classe WeakMap

A RFC da classe WeakMap cria uma nova classe chamada WeakMap que parece um pouco com a SplObjectStorage.

A ideia é que você poderá criar um map objeto -> valor com ela, sem impeding que o objeto seja apagado pelo garbage collector. Por isso o nome Weak, justamente porque existe uma referência fraca (weak reference) entre o objeto chave e o map.

Removendo um objeto mapeado da memória causará a remoção do valor dentro do map. Como no seguinte trecho de código:

$map = new WeakMap();
$obj = new DateTime('today');

$map[$obj] = 100;

// Mostra uma chave
var_dump($map);

// Remove $obj da memória
unset($obj);

// WeakMap está vazio
var_dump($map);

Atualização (20/01/2020): se você quiser experimentar, tem um polyfill disponível para o PHP 7.4; Chama-se BenMorel/weakmap-polyfill.

Exceções do tipo TypeError serão lançadas em erros de parâmetros

Sempre que você causa um type error numa função de usuário, uma exceção é lançada. Para funções internas o PHP apenas mostra um warning e retorna null por padrão.

A RFC de TypeError consistentes torna os dois comportamentos consistentes, lançando uma exceção de TypeError nos dois casos.

Chaves de array implícitas serão mais consistentes

Sempre que você utiliza índices negativos na função array_fill, ela irá gerar o primeiro índice negativo e depois pular para 0 (🤦‍♀️). Tipo assim:

$a = array_fill(-2, 3, true);
var_dump($a);

// Saída
array(3) {
  [-2] =>
  bool(true)
  [0] =>
  bool(true)
  [1] =>
  bool(true)
}

A RFC Negative Array Index visa corrigir esse comportamento fazendo com que o array_fill ande corretamente pelos índices negativos:

$a = array_fill(-2, 3, true);
var_dump($a);

// Saída
array(3) {
  [-2] =>
  bool(true)
  [-1] =>
  bool(true)
  [0] =>
    bool(true)
  }

Fatal Error em sobrecarga de métodos

Sempre que uma classe define uma assinatura de método e uma herança tenta sobrecarregar este método (mudando sua assinatura) um warning é lançado.

Esta RFC do Nikita Popov transforma este comportamento para lançar um Fatal Error sempre que uma sobrecarga ocorre.

Aqui vai um exemplo de código que quebrará no PHP 8:

class A
{
  function x(int $a): int
  {
    // ...
  }
}

class B extends A
{
  // A assinatura mudou
  // Fatal Error aqui.
  function x(float $a): float
  {
    // ...
  }
}

Atualização da DOM API para bater com o padrão DOM

Esta RFC também pede um post para si.

Mas basicamente ela adiciona algumas interfaces e classes para tornar a API da ext/dom compatível com o atual padrão DOM que está constantemente sendo atualizado.


O que TALVEZ entre na versão 8.0 do PHP?

Existem algumas RFCs que ainda estão sendo discutiads. Elas podem ser aceitas ou negadas a qualquer momento. Existem muitas coisas relacionadas ao core da linguagem e sua sintaxe.

Aqui vai a lista:

Severidade de erros

A RFC da severidade de erros pretende revisar a forma como algumas funcionalidades tratam erros na linguagem.

Por exemplo, o tão famoso Invalid argument supplied for foreach() poderá pular de Warning para TypeError Exception.

Permitir o uso de ::class em objetos

Basicamente nomes de classe dinâmicos não são permitidos em tempo de compilação. Então um código como o seguinte gera um erro fatal:

$a = new DateTime();
var_dump($a::class);
// PHP Fatal error:  Dynamic
// class names are not allowed
// in compile-time
// ::class fetch in...

Nesta RFC o código acima será aceitável.

Tornar static um tipo de retorno válido, como self

Da mesma forma como podemos usar self como tipo de retorno para funções, a RFC de static return torna disponível static como outro tipo válido de retorno.

Desta forma funções como a seguinte serão consideradas válidas:

class A
{
  public function b(): static
  {
    return new static();
  }
}

Sintaxe de variáveis consistentes

Esta aqui é sobre mudanças sintáticas e mudará algumas funcionalidades.

Eu recomendo dar uma olhada na RFC para obter mais detalhes. As funcionalidades afetadas incluem:

Otimizar o lookup de funções e constantes

A RFC sobre lookup de funções e constantes adiciona um novo declare() que impede o PHP de fazer alguns lookups em tempo de execução.

Sempre que você estiver num código dentro de namespace e tenta utilizar uma função ou constante de escopo global sem prefixar com uma barra invertida (\), o PHP primeiro tentará buscá-la no namespace atual e só então procurar no namespace global.

Adicionando a diretiva disable_ambiguous_element_lookup=1, o PHP tentará buscar diretamente no escopo global. Aqui vai um exemplo (da RFC):

namespace MyNS;
declare(
    strict_types=1,
    disable_ambiguous_element_lookup=1
);
use function OtherNS\my_function;
use const OtherNS\OTHER_CONST;

if (
  // lookup de função!!
  version_compare(
    // lookup de constante!!
    PHP_VERSION,
    '8.0.5'
  ) >= 0
) {
    // ...
}

Caso disable_ambiguous_element_lookup fosse zero no exemplo acima, o PHP tentaria encontrar MyNS\PHP_VERSION e MyNS\version_compare primeiro, entenderia que não existem e só então buscaria no escopo global as referências para \PHP_VERSION e \version_compare.

Quando disable_ambiguous_element_lookup for um, este lookup extra não é mais necessário e o PHP irá diretamente ao escopo global, trazendo \PHP_VERSION e \version_compare.

A diretiva Strict Operators

A RFC de operadores estritos traria uma nova diretiva chamada strict_operators. Quando ligada, algumas comparações se comportariam de forma diferente.

Aqui alguns exemplos (da RFC):

10 > 42;        // false
3.14 < 42;      // true

"foo" > "bar";  // TypeError("Unsupported type string for comparison")
"foo" > 10;     // TypeError("Operator type mismatch string and int for comparison")

"foo" == "bar"; // false
"foo" == 10;    // TypeError("Operator type mismatch string and int for comparison")
"foo" == null;  // TypeError("Operator type mismatch string and null for comparison")

true > false;   // true
true != 0;      // TypeError("Operator type mismatch bool and int for comparison")

[10] > [];      // TypeError("Unsupported type array for comparison")
[10] == [];     // false

"120" > "99.9";               // TypeError("Unsupported type string for comparison")
(float)"120" > (float)"99.9"; // true

"100" == "1e1";               // false
(int)"100" == (int)"1e2";     // true

"120" <=> "99.9";             // TypeError("Unsupported type string for comparison")

As mudanças são bem mais amples que este pequeno exemplo e estão fora do escopo deste post. Verifique a RFC para mais ou me dá um ping no twitter caso queira que eu escreva um pouco mais sobre esta! 😉


As RFCs abaixo ainda estão sob discussão e a maioria têm algo relacionado a versões passadas do PHP, não tendo sido lançadas a tempo ou algo parecido. Eu não irei as descrever em detalhe por agora, por não sentir que trarão grandes mudanças à linguagem.

Eu irei, é claro, manter esta lista atualizada para tomar certeza de que estou errado.

Aqui vão elas:

Auto Increment na cópia na gravação

Link para a RFC.

Esta RFC foi originalmente pensada para o PHP 7.4 e ainda está sob discussão. Eu esperaria que fosse apontada para a versão 8.0 desta vez, mas não há certezas.

Sintaxe alternativa do "use" em Closures

Link para a RFC.

Esta RFC originalmente buscava ser integrada na "próxima minor verson", que naquele tempo seria a versão 7.4.

Aplicar um declare() em todo o Namespace 🔥

Link para a RFC.

Permitir espaços no fim de strings numéricas

Link para a RFC.

Esta RFC também visava a versão 7.4 mas não conseguiu ser votada a tempo.

Permitir type casting de valores nullable

Link para a RFC.

Aparentemente o fork que continha as mudanças foi apagado e o Pull Request fechado. Não parece crível que será integrado ao PHP a menos que alguém resolva tomar conta.


Por enquanto é só. Eu adicionarei algumas Atualizações nos tópicos acima com o tempo, sempre que a comunidade andar com alguma RFC e eu tiver a oportunidade de ver algum status mudando.

Se você encontrou algo errado ou gostaria de adicionar alguma coisa que eu deixei passar aqui, sinta-se convidado(a) a me dar um ping no twitter ou abrir uma issue no repositório público.