Alterações incompatíveis com versões anteriores

PHP Core

Restrições de acesso ao $GLOBALS

Acesso ao array $GLOBALS agora está sujeito a uma série de restrições. Acesso de leitura e escrita a elementos individuais de array como $GLOBALS['var'] continuam funcionando como estão. Acesso somente leitura para todo o array $GLOBALS também continua a ser suportado. No entanto, acesso de escrita para todo o array $GLOBALS não é mais suportado. Por exemplo, array_pop($GLOBALS) resultará em um erro.

Uso de variáveis static em Métodos Herdados

Quando um método usando variáveis estáticas é herdado (mas não sobreposto), o método herdado agora irá compartilhar variáveis estáticas com o método pai.

<?php
class A {
    public static function counter() {
        static $counter = 0;
        $counter++;
        return $counter;
    }
}
class B extends A {}
var_dump(A::counter()); // int(1)
var_dump(A::counter()); // int(2)
var_dump(B::counter()); // int(3), anteriormente int(1)
var_dump(B::counter()); // int(4), anteriormente int(2)
?>
Isso significa que variávies estáticas em métodos agora se comportam da mesma maneira que propriedades estáticas.

Parâmetros opcionais especificados antes de parâmetros obrigatórios

Um parâmetro opcional especificado antes de parâmetros obrigatórios agora é sempre tratado como obrigatório, mesmo ao chamar usando argumentos nomeados. A partir do PHP 8.0.0, mas antes do PHP 8.1.0, a função abaixo emite um aviso de descontinuação na definição, mas executa com sucesso quando chamada. A partir do PHP 8.1.0, um erro da classe ArgumentCountError é lançado, assim como seria lançado ao chamar argumentos posicionais.

<?php
function fazeriogurte($recipiente = "tigela", $sabor)
{
    return "Fazendo um(a) $recipiente de iogurte de $sabor.\n";
}
try
{
    echo fazeriogurte(sabor: "framboesa");
}
catch (Error $e)
{
    echo get_class($e), ' - ', $e->getMessage(), "\n";
}
?>

Saída do exemplo acima no PHP 8.0:

Deprecated: Required parameter $sabor follows optional parameter $recipiente
 in example.php on line 3
Fazendo um(a) tigela de iogurte de framboesa.

Saída do exemplo acima no PHP 8.1:

Deprecated: Optional parameter $recepiente declared before required parameter
 $sabor is implicitly treated as a required parameter in example.php on line 3
ArgumentCountError - fazeriogurte(): Argument #1 ($recepiente) not passed

Note que um valor padrão de null pode ser usado antes de parâmetros obrigatórios para especificar um tipo anulável, mas o parâmetro ainda será obrigatório.

Compatibilidade de Tipo de Retorno com Classes Internas

A maioria dos métodos internos não-finais agora obrigam métodos que fazem sobrescrita a declarar um tipo de retorno compatível, do contrário um aviso de descontinuação é emitido durante a validação de herança. Caso o tipo de retorno não possa ser declarado para um método que faz sobrescrita devido a questões de compatilidade entre versões PHP, um atributo ReturnTypeWillChange pode ser adicionado para silenciar o aviso de descontinuação.

Novas Palavras-chave

readonly agora é uma palavra-chave. No entanto, ela ainda pode ser usada como nome de função.

never agora é uma palavra reservada, então ela não pode ser usada para nomear uma classe, interface ou trait, e também é proibida de ser usada em namespaces.

Migração de Recurso para Objeto

Diversos resources foram migrados para objects. Checagens de valor de retorno usando is_resource() devem ser trocadas para checagens por false.

MySQLi

mysqli_fetch_fields(), e mysqli_fetch_field_direct() agora irão sempre retornar 0 para a max_length. Essa informação pode ser computada iterando sobre o conjunto de resultados, e obtendo o tamanho máximo. Era isso que o PHP estava fazendo internamente anteriormente.

A opção MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH não tem mais efeito.

A opção MYSQLI_STORE_RESULT_COPY_DATA Não tem mais efeito. Passar qualquer valor para o parâmetro mode do mysqli::store_result() não tem mais efeito.

mysqli::connect() agora retorna true em vez de null em caso de sucesso.

O modo de manipulação de erros padrão foi alterado de "silent" para "exceptions" Veja a página Modo de relatório do MySQLi para mais detalhes sobre o que isso emplica, e como definir esse atributo explicitamente. Para restaurar o comportamento anterior use: mysqli_report(MYSQLI_REPORT_OFF);

Classes estendendo mysqli_stmt::execute() agora são obrigadas a especificar o parâmetro opcional adicional.

MySQLnd

A diretiva INI mysqlnd.fetch_data_copy foi removida. Isso não deve resultar em mudanças comportamentais visíveis pelo usuário.

OpenSSL

Chaves privadas EC agora serão exportadas no formato PKCS#8 em vez de formatos tradicionais, assim como todas as outras chaves.

openssl_pkcs7_encrypt() e openssl_cms_encrypt() agora irão por padrão usar AES-128-CBC em vez de RC2-40. O cifrador RC2-40 é considerado inseguro e não é habilitado por padrão pelo OpenSSL 3.

PHP Data Objects

PDO::ATTR_STRINGIFY_FETCHES agora stringifica valores de tipo bool para "0" iy "1". Anteriormente bools não eram stringificados.

Chamar PDOStatement::bindColumn() com PDO::PARAM_LOB agor irá constantemente vincular um resultado de stream quando PDO::ATTR_STRINGIFY_FETCHES não está habilitado. Anteriormente, o resultado seria uma stream ou string dependendo do driver de banco de dados utilizado e a hora que a vinculação é realizada.

Driver MySQL

Inteiros e floats em conjuntos de resultados agora serão retornados usando tipos nativos do PHP em vez de strings ao usar declarações preparadas emuladas. Isso corresponde ao comportamento das declarações preparadas nativas. O comportamento anterior pode ser restaurado habilitando a opção PDO::ATTR_STRINGIFY_FETCHES.

Driver SQLite

Inteiros e floats em conjuntos de resultados agora serão retornados usando tipos nativos do PHP. O comportamento anterior pode ser restaurado habilitando a opção PDO::ATTR_STRINGIFY_FETCHES.

Phar

Para cumprir com a interface ArrayAccess, Phar::offsetUnset() e PharData::offsetUnset() não retorna mais um bool.

Biblioteca Padrão

version_compare() não aceita mais abreviações de operadores não documentados.

htmlspecialchars(), htmlentities(), htmlspecialchars_decode(), html_entity_decode(), e get_html_translation_table() agora usam ENT_QUOTES | ENT_SUBSTITUTE em vez de ENT_COMPAT por padrão. Isso significa que ' é escapada para &#039; enquanto antes nada era feito. Adicionalmente, UTF-8 malformado será substituído por um caractere de substituição Unicode, ao invés de resultar em uma string vazia.

debug_zval_dump() agora imprime a refcount de wrappers de referência com sua refcount, em vez de apenas prefixar & ao valor. Isso modela de forma mais precisa a representação de referência desde o PHP 7.0.

debug_zval_dump() agora imprime interned em vez de uma refcount falso para strings internadas e arrays imutáveis.

Biblioteca Padrão do PHP (SPL)

SplFixedArray, agora será codificado em JSON como um array