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

PHP Core

Comparação entre String e Número

Comparações não estritas entre números e strings não numéricas, agora funcionam convertendo o número em string e comparando as strings. As comparações entre números e strings numéricas continuam funcionando como antes. Notavelmente, isso significa que a comparação: 0 == "not-a-number" agora é considerada falsa.

Comparação Antes Depois
0 == "0" true true
0 == "0.0" true true
0 == "foo" true false
0 == "" true false
42 == " 42" true true
42 == "42foo" true false

Outras mudanças incompatíveis

  • match agora é uma palavra reservada.

  • mixed agora é uma palavra reservada, portanto, não pode ser usado para nomear uma classe, interface ou trait, e também é proibido de ser usado em namespaces.

  • As falhas de asserção agora são lançadas por padrão. Se o comportamento antigo é desejado, assert.exception=0 pode ser definido nas configurações INI.

  • Métodos com o mesmo nome de classe não são mais interpretados como construtores. O método __construct() deve ser utilizado em seu lugar.

  • A capacidade de chamar métodos não estáticos estaticamente foi removida. Por isso a função is_callable() irá falhar ao verificar um método não estático com um nome de classe (deve se realizar uma verificação com uma instância de objeto).

  • Foram removidas as conversões de tipos, (real) e (unset).

  • A diretiva do php.ini track_errors foi removida. Isto significa que a variável php_errormsg não está mais disponível. A função error_get_last() deve ser utilizada em seu lugar.

  • A capacidade de definir constantes que não diferenciam maiúsculas de minúsculas foi removida. O terceiro argumento para a função define() não pode ser mais true.

  • A capacidade de especificar um auto carregamento utilizando a função __autoload() foi removida. A função spl_autoload_register() deve ser utilizada em seu lugar.

  • O argumento errcontext não será mais usado para manipulação de erros personalizados definido com a função set_error_handler().

  • A função create_function() foi removida. Ao invés disso, funções anônimas devem ser utilizadas.

  • A função each() foi removida. foreach ou ArrayIterator devem ser utilizados em seu lugar.

  • Foi removida a capacidade de desvincular this de closures que foram criadas a partir de um método, usando Closure::fromCallable() ou ReflectionMethod::getClosure().

  • A habilidade de desvincular this de closures que contêm usos de this também foi removida.

  • A habilidade de utilizar a função array_key_exists() com objetos foi removida. as funções isset() ou property_exists() devem ser usadas em seu lugar.

  • O comportamento da função array_key_exists() com relação ao tipo do parâmetro key agora é consistente com a função isset() e acesso normal à arrays. Todos os tipos de chave agora usam as coerções usuais e as chaves de array/objeto lançam um TypeError.

  • Qualquer array com número n em sua primeira posição utilizará n+1 em sua próxima chave implícita mesmo se n for negativo.

  • O nível de error_reporting padrão agora é E_ALL. Anteriormente excluía E_NOTICE e E_DEPRECATED.

  • display_startup_errors agora é habilitado por padrão.

  • Usar parent dentro de uma classe sem pai agora produzirá um erro fatal em tempo de execução.

  • O operador @ não irá mais silenciar erros fatais (E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR, E_PARSE). Manipuladores de erros que esperam que error_reporting seja 0 quando @ é usado, devem ser ajustados para usar uma verificação de máscara:

    <?php
    // Substituir isso ...
    function my_error_handler($err_no, $err_msg, $filename, $linenum) {
    if (
    error_reporting() == 0) {
    return
    false;
    }
    // ...
    }

    // ... por isso:
    function my_error_handler($err_no, $err_msg, $filename, $linenum) {
    if (!(
    error_reporting() & $err_no)) {
    return
    false;
    }
    // ...
    }
    ?>

    Adicionalmente, cuidados devem ser tomados para que mensagens de erro não sejam mostradas no ambiente de produção, o que pode resultar em vazamento de informações. Certifique-se de que a diretiva display_errors=Off seja usada em conjunto com o log de erros.

  • #[ não é mais interpretado como o início de um comentário, já que esta sintaxe é utilizada agora para atributos.

  • Erros de herança devido a assinaturas de método incompatíveis (violações de LSP) agora sempre gerarão um erro fatal. Antes, um aviso era gerado em alguns casos.

  • A precedência dos operadores de concatenação foi modificada em relação ao bitshifts tanto na adição como na subtração.

    <?php
    echo "Sum: " . $a + $b;
    // Era interpretado como:
    echo ("Sum: " . $a) + $b;
    // e passa a ser interpretado como:
    echo "Sum:" . ($a + $b);
    ?>

  • Argumentos com um valor padrão que avaliam null em tempo de execução, não irão mais marcar o tipo do parâmetro como implícito. Um tipo explícito nulo, ou explicitamente null como argumento padrão deve ser usado em seu lugar.

    <?php
    // Subistituir
    function test(int $arg = CONST_RESOLVING_TO_NULL) {}
    // Por isso
    function test(?int $arg = CONST_RESOLVING_TO_NULL) {}
    // Ou isso
    function test(int $arg = null) {}
    ?>

  • Uma série de avisos foram convertidos para exceções do tipo Error:

    • A tentativa de escrita em uma propriedade de um não-objeto. Anteriormente isso criava implicitamente um objeto stdClass para strings nulas, falsas e vazias.
    • A tentativa de anexar um elemento a um array para a qual a chave PHP_INT_MAX já está em uso.
    • Tentar usar um tipo inválido (array ou objeto) como uma chave de array ou deslocamento de string.
    • A tentativa de escrever em um índice de array de um valor escalar.
    • Tentar descompactar um não-array/Traversable.
    • Tentar acessar constantes não qualificadas que são indefinidas. Anteriormente, os acessos constantes não qualificados resultavam em um aviso e eram interpretados como strings.
    • Passar o número errado de argumentos para uma função sem argumento variadic ira lançar uma exceção ArgumentCountError.

    Uma série de notificações foram convertidas em avisos:

    • A tentativa de leitura em uma variável não definida.
    • A tentativa de leitura em uma propriedade não definida.
    • A tentativa de leitura em uma chave de array não definido.
    • A tentativa de leitura em uma propriedade de um não-objeto.
    • A tentativa de acesso em um índice de array em um não-array.
    • A tentativa de conversão de um array para uma string.
    • A tentativa de usar um resource como uma chave de array.
    • A tentativa de usar null, um booleano ou um número de ponto flutuante(float) como uma posição em uma string.
    • A tentativa de leitura em uma posição fora dos limites de uma string.
    • A tentativa de atribuir uma string vazia a uma posição de uma string.

  • A tentativa de atribuir múltiplos bytes em uma posição de uma string agora emite um aviso.

  • Caracteres inesperados no código fonte (como bytes NUL fora de strings) agora irá resultar em uma exceção ParseError em vez de um aviso do compilador.

  • As exceções não capturadas agora passam por "desligamento limpo", o que significa que os destrutores são chamados após uma exceção não detectada.

  • O erro fatal em tempo de compilação "Only variables can be passed by reference" foi adiado até o tempo de execução, e convertido em uma exceção de Error "Argument cannot be passed by reference".

  • Alguns alertas do tipo "Only variables should be passed by reference" foram convertidas para exceções do tipo "Argument cannot be passed by reference"

  • O nome gerado para classes anônimas foi modificado. Agora, inclui o nome da primeira classe ou interface:

    <?php
    new class extends ParentClass {};
    // -> ParentClass@anonymous
    new class implements FirstInterface, SecondInterface {};
    // -> FirstInterface@anonymous
    new class {};
    // -> class@anonymous
    ?>

    O nome mostrado acima ainda é seguido por um byte NUL e um sufixo único.

  • As referências de método de traits não absolutas em adaptações de alias de traits agora precisam ser inequívocas:

    <?php
    class X {
    use
    T1, T2 {
    func as otherFunc;
    }
    function
    func() {}
    }
    ?>

    Se T1::func() e T2::func() existem, este código anteriormente era aceito de forma silenciosa e func assumia referência a T1::func. Agora irá gerar um erro fatal, e T1::func ou T2::func precisam ser escritos explicitamente.

  • A assinatura de métodos abstratos definido nas características agora é verificada no método de implementação da classe:

    <?php
    trait MyTrait {
    abstract private function
    neededByTrait(): string;
    }

    class
    MyClass {
    use
    MyTrait;

    // Erro por conta do retorno desalinhado.
    private function neededByTrait(): int { return 42; }
    }
    ?>

  • Funções desabilitadas agora são tratadas da mesma forma que funções não existentes. Ao chamar uma função desabilitada será informado que ela é desconhecida, e redefinir uma função desabilitada agora é possível.

  • Os stream wrappers data:// não podem mais ser writable (gravável), indo de encontro ao comportamento documentado.

  • Os operadores aritméticos e bitwise (bit a bit) +, -, *, /, **, %, <<, >>, &, |, ^, ~, ++, -- irão agora apresentar um TypeError quando um dos operandos estiver em um array, resource ou em um object não sobrecarregado (non-overloaded). A única exceção a isto é a operação de mesclagem de array com +, que permanece suportada.

  • A conversão de float para string agora sempre terá o mesmo comportamento, independentemente da localidade.

    <?php
    setlocale
    (LC_ALL, "de_DE");
    $f = 3.14;
    echo
    $f, "\n";
    // Anteriormente: 3,14
    // Agora: 3.14
    ?>

    Veja as funções printf(), number_format() e NumberFormatter() para customizar a formatação de números.

  • O suporte para chaves (curly braces), cujo uso para acesso de deslocamento estava descontinuado, foi removido.

    <?php
    // Ao invés de:
    $array{0};
    $array{"key"};
    // Usar:
    $array[0];
    $array["key"];
    ?>

  • Aplicar o modificador final ou método privado agora irá produzir um aviso, a menos que o método seja o construtor.

  • Se um objeto construtor chama a função exit(), o objeto destrutor não será chamado. Isto vai de encontro ao comportamento que o construtor lança.

  • Nomes de Namespace não podem mais conter espaços em branco: Enquanto Foo\Bar será reconhecido como um nome de Namespace, Foo \ Bar não será. Por outro lado, as palavras-chave agora serão permitidas como segmentos de um namespace, o que permite a mudança na interpretação do código: new\x agora é o mesmo que constant('new\x'), e não new \x().

  • Os ternários aninhados agora exigem parênteses explícitos.

  • debug_backtrace() e Exception::getTrace() agora não mais apresentam referências aos argumentos. Não será possível mudar os argumentos de uma função através de um backtrace.

  • O uso de strings numéricas foi modificado para ser mais intuitivo e menos sujeito a erros. Seguindo os espaços em branco, é permitido agora strings numéricas para tratamento de consistência contendo espaços em branco. Isso afeta principalmente:

    • A função is_numeric()
    • Comparações string a string
    • Declaração de tipos
    • Operações de incremento e decremento

    O conceito de um "leading-numeric string" foi praticamente abandonado; os casos onde permanecem são para facilitar a migração. Strings que emitem um E_NOTICE "A non well-formed numeric value encountered" agora emitirão um E_WARNING "A non-numeric value encountered" e todas as strings que emitiram um E_WARNING "A non-numeric value encountered" agora lançarão um erro TypeError. Isso afeta principalmente:

    • Operações aritméticas
    • Operações bit a bit

    Esta mudança do E_WARNING para TypeError também afeta o E_WARNING "Illegal string offset 'string'" para o posicionamento ilegal de strings. O comportamento de conversões explícitas de strings para int/float não foi alterado.

  • Métodos mágicos agora podem ter argumentos e retornar tipos verificados se eles foram declarados. As assinaturas devem corresponder à seguinte lista:

    • __call(string $name, array $arguments): mixed
    • __callStatic(string $name, array $arguments): mixed
    • __clone(): void
    • __debugInfo(): ?array
    • __get(string $name): mixed
    • __invoke(mixed $arguments): mixed
    • __isset(string $name): bool
    • __serialize(): array
    • __set(string $name, mixed $value): void
    • __set_state(array $properties): object
    • __sleep(): array
    • __unserialize(array $data): void
    • __unset(string $name): void
    • __wakeup(): void

  • As chaves do array passados para a função call_user_func_array() agora podem ser interpretadas como nomes de parâmetros, em vez de serem silenciosamente ignoradas.

  • A declaração da função chamada assert() dentro de um namespace não é mais permitida e gera um E_COMPILE_ERROR. A função assert() recebe um tratamento especial pelo motor do PHP, o que pode levar a comportamentos inconsistentes quando definido como uma função de namespace com o mesmo nome.

Migração de Resource para Objeto

Diversos resources foram migrados para objects. Verificações de valor de retorno usando a função is_resource() devem ser substituídas por checagens para false.

COM e .Net (Windows)

A capacidade de importar constantes que não diferenciam maiúsculas de minúsculas de bibliotecas de tipos foi removida. O segundo argumento para com_load_typelib() não pode mais ser falso; com.autoregister_casesensitive não pode mais ser desabilitado; marcadores que não diferenciam maiúsculas de minúsculas em com.typelib_file são ignorados.

CURL

CURLOPT_POSTFIELDS não aceita mais objetos como arrays. Para interpretar um objeto como um array, executar uma conversão explícita de (array). O mesmo se aplica a outras opções que aceitam arrays também.

Data e hora

mktime() e gmmktime() agora requer pelo menos um argumento. time() pode ser usado para obter o registro de data e hora atual.

DOM

Classes não implementadas da extensão DOM que não tinham comportamento e continham dados de teste foram removidos. Essas classes também foram removidas na versão mais recente do DOM padrão:

  • DOMNameList
  • DomImplementationList
  • DOMConfiguration
  • DomError
  • DomErrorHandler
  • DOMImplementationSource
  • DOMLocator
  • DOMUserDataHandler
  • DOMTypeInfo
  • DOMStringExtend

Métodos não implementados da extensão DOM que não tinham comportamento foram removidos:

  • DOMNamedNodeMap::setNamedItem()
  • DOMNamedNodeMap::removeNamedItem()
  • DOMNamedNodeMap::setNamedItemNS()
  • DOMNamedNodeMap::removeNamedItemNS()
  • DOMText::replaceWholeText()
  • DOMNode::compareDocumentPosition()
  • DOMNode::isEqualNode()
  • DOMNode::getFeature()
  • DOMNode::setUserData()
  • DOMNode::getUserData()
  • DOMDocument::renameNode()

Enchant

Exif

read_exif_data() foi removido; exif_read_data() deve ser usado em seu lugar.

Filter

  • A FILTER_FLAG_SCHEME_REQUIRED e FILTER_FLAG_HOST_REQUIRED sinalizadores para o filtro FILTER_VALIDATE_URL foram removidas. O scheme e host são (e foram) sempre necessários.

  • A fonte INPUT_REQUEST e INPUT_SESSION para filter_input() etc. foram removidos. Estes nunca foram implementados e seu uso sempre gerou um warning.d

GD

  • A função descontinuada image2wbmp() foi removida.

  • As funções descontinuadas png2wbmp() e jpeg2wbmp() foram removidas.

  • O parametro padrão mode de imagecropauto() não aceita mais -1. IMG_CROP_DEFAULT deve ser usado no lugar.

  • No Windows, php_gd2.dll foi renomeado para php_gd.dll.

GMP

gmp_random() foi removida. Uma das gmp_random_range() ou gmp_random_bits() deve ser usado no lugar.

Iconv

implementações de iconv que não definem corretamente errno em caso de erros não são mais suportadas.

IMAP

Funções de Internacionalização

  • A constante descontinuada INTL_IDNA_VARIANT_2003 foi removida.

  • A constante descontinuada Normalizer::NONE foi removida.

LDAP

MBString

OCI8

  • A classe OCI-Lob agora é chamada de OCILob, e a a classe OCI-Collection agora se chama OCICollection para conformidade de nome imposta pelas ferramentas de anotação de tipo PHP 8 arginfo.

  • Várias funções de alias foram marcadas como descontinuadas.

  • oci_internal_debug() e seu alias ociinternaldebug() foram removidos.

ODBC

OpenSSL

Expressões regulares (Perl-Compatible)

Ao passar sequências de escape inválidas, elas não são mais interpretadas como literais. Esse comportamento anteriormente exigia o modificador X – que agora é ignorado.

Objetos de dados do PHP

  • The default error handling mode has been changed from "silent" to "exceptions". See Errors and error handling for details.

  • As assinaturas de alguns métodos PDO foram alteradas:

    • PDO::query(string $query, ?int $fetchMode = null, mixed ...$fetchModeArgs)
    • PDOStatement::setFetchMode(int $mode, mixed ...$args)

PDO ODBC

The php.ini directive pdo_odbc.db2_instance_name foi removido.

PDO MySQL

PDO::inTransaction() agora relata o estado real da transação da conexão, em vez de uma aproximação mantida pelo PDO. Se uma consulta que é sujeito para "confirmação implícita" é executado, PDO::inTransaction() posteriormente retornará false, pois uma transação não está mais ativa.

PostgreSQL

  • A sintaxe descontinuada de pg_connect() usando vários parâmetros em vez de uma string de conexão não é mais suportada.

  • As assinaturas descontinuadas de pg_lo_import() e pg_lo_export() que passam a conexão como o último argumento não são mais suportadas. A conexão deve ser passada como primeiro argumento.

  • pg_fetch_all() agora retornará uma matriz vazia em vez de false para resultado conjuntos com zero linhas.

Phar

Os metadados associados a um phar não serão mais serializados automaticamente, para corrigir possíveis vulnerabilidades de segurança devido à instanciação de objetos, carregamento automático etc.

Reflection

  • As assinaturas do método

    • ReflectionClass::newInstance($args)
    • ReflectionFunction::invoke($args)
    • ReflectionMethod::invoke($object, $args)

    foram alterados para:

    • ReflectionClass::newInstance(...$args)
    • ReflectionFunction::invoke(...$args)
    • ReflectionMethod::invoke($object, ...$args)

    O código que deve ser compatível com PHP 7 e PHP 8 pode usar as seguintes assinaturas para serem compatíveis com ambas as versões:

    • ReflectionClass::newInstance($arg = null, ...$args)
    • ReflectionFunction::invoke($arg = null, ...$args)
    • ReflectionMethod::invoke($object, $arg = null, ...$args)

  • O método ReflectionType::__toString() agora retornará uma completa representação de depuração do tipo, e não está mais descontinuada. Em particular, o resultado incluirá um indicador de nulidade para tipos anuláveis. O formato do valor de retorno não é estável e pode mudar entre as versões do PHP.

  • Métodos export() de reflexão foram removidos. Em vez disso, os objetos de reflexão podem ser convertidos em string.

  • ReflectionMethod::isConstructor() e ReflectionMethod::isDestructor() agora também retorna true por __construct() e __destruct() métodos de interfaces. Anteriormente, isso só seria verdade para métodos de classes e traits.

  • O método ReflectionType::isBuiltin() foi movido para ReflectionNamedType. ReflectionUnionType não possui esse método.

Sockets

  • As constantes descontinuadas AI_IDN_ALLOW_UNASSIGNED e AI_IDN_USE_STD3_ASCII_RULES flags para socket_addrinfo_lookup() foram removidas.

Biblioteca PHP padrão (SPL)

Biblioteca padrão

  • assert() não avaliará mais argumentos de string, em vez disso, eles serão tratados como qualquer outro argumento. assert($a == $b) deve ser usado em vez de assert('$a == $b'). O assert.quiet_eval diretiva ini e as constantes ASSERT_QUIET_EVAL também foram removidas, pois não seriam mais ter qualquer efeito.

  • parse_str() não pode mais ser usado sem especificar um array de resultados.

  • The string.strip_tags filter has been removed.

  • O argumento needle de strpos(), strrpos(), stripos(), strripos(), strstr(), strchr(), strrchr() e stristr() agora sempre será interpretado como uma string. Anteriormente agulhas não-string foram interpretadas como um ponto de código ASCII. Uma chamada explícita para chr() pode ser usado para restaurar o comportamento anterior.

  • O argumento needle para strpos(), strrpos(), stripos(), strripos(), strstr(), stristr() e strrchr() podem agora estar vazios.

  • O argumento length para substr(), substr_count(), substr_compare() e iconv_substr() agora pode ser null. null os valores se comportarão como se não houvesse argumento de comprimento fornecido e, portanto, retornará o restante da string em vez de uma string vazia.

  • O argumento length para array_splice() agora pode ser null. null os valores se comportarão de forma idêntica à omissão do argumento, removendo assim tudo do offset até o final do array.

  • O argumento args de vsprintf(), vfprintf() e vprintf() agora devem ser um array. Anteriormente qualquer tipo era aceito.

  • A opção 'salt' de password_hash() não é mais suportado. Se a opção 'salt' for usada, um aviso será gerado, o salt é ignorado e um salt gerado é usado em seu lugar.

  • A função quotemeta() agora retornará uma string vazia se uma string vazia foi passada. Anteriormente false era devolvido.

  • As seguintes funções foram removidas.

  • FILTER_SANITIZE_MAGIC_QUOTES foi removida.

  • Chamar implode() com parâmetros na ordem inversa ($pieces, $glue) não é mais suportado.

  • parse_url() agora distinguirá consultas e fragmentos ausentes e vazios:

    • http://example.com/foo → query = null, fragment = null
    • http://example.com/foo? → query = "", fragment = null
    • http://example.com/foo# → query = null, fragment = ""
    • http://example.com/foo?# → query = "", fragment = ""
    Anteriormente, todos os casos resultavam em consultas e fragmentos null.

  • var_dump() e debug_zval_dump() agora serão números de ponto flutuante usando serialize_precision em vez de precisão. Em uma configuração padrão, isto significa que os números de ponto flutuante agora são impressos com total precisão por essas funções depuradoras.

  • Se o array retornado por __sleep() contiver propriedades inexistentes, estas agora são silenciosamente ignoradas. Anteriormente, tais propriedades teriam sido serializadas como se tivessem o valor null.

  • A localidade padrão na inicialização agora é sempre "C". Nenhuma localidade é herdada do ambiente por padrão. Anteriormente, LC_ALL era definida como "C", enquanto LC_CTYPE era herdada do ambiente. No entanto, algumas funções não respeitavam a localidade herdada sem uma chamada explícita setlocale(). Uma chamada setlocale() explícita agora é sempre necessária se um componente de localidade deve ser alterado do padrão.

  • O fallback DES descontinuado em crypt() foi removido. Se um desconhecido formato salt for passado para crypt(), a função falhará com *0 em vez de voltar para um hash DES fraco agora.

  • A especificação de rodadas fora do intervalo para SHA256/SHA512 crypt() agora falhará com *0 em vez de fixar no limite mais próximo. Isso corresponde ao comportamento da glibc.

  • O resultado das funções de classificação pode ter mudado, se o array contiver elementos que comparam como igual.

  • Quaisquer funções que aceitam retornos de chamada que não são explicitamente especificados para aceitar parâmetros por referência agora avisará se um retorno de chamada com parâmetros de referência for usado. Exemplos incluem array_filter() e array_reduce(). Este já era o caso para a maioria, mas não para todas as funções anteriormente.

  • O wrapper de fluxo HTTP usado por funções como file_get_contents() agora anuncia HTTP/1.1 em vez de HTTP/1.0 por padrão. Isso não muda o comportamento do cliente, mas pode fazer com que os servidores respondam de forma diferente. Para manter o comportamento antigo, defina a opção de contexto de fluxo 'protocol_version', por exemplo

    <?php
    $ctx
    = stream_context_create(['http' => ['protocol_version' => '1.0']]);
    echo
    file_get_contents('http://example.org', false, $ctx);
    ?>

  • Chamar crypt() sem um salt explícito não é mais suportado. Se você gostaria de produzir um hash forte com salt gerado automaticamente, use password_hash() em vez disso.

  • substr(), mb_substr(), iconv_substr() e grapheme_substr() agora fixa consistentemente os deslocamentos fora dos limites à string fronteira. Anteriormente, false era retornado em vez da string vazia em alguns casos.

  • No Windows, as funções de execução do programa (proc_open(), exec(), popen() etc.) usando o shell, agora execute consistentemente %comspec% /s /c "$commandline", que tem o mesmo efeito que executar $commandline (sem aspas adicionais).

Sysvsem

  • O parâmetro auto_release de sem_get() foi alterado para aceitar valores booleanos em vez de int.

Tidy

Tokenizer

  • Tokens T_COMMENT não incluirão mais uma quebra de linha à direita. Em vez disso, a quebra de linha será parte de um token T_WHITESPACE seguinte. Deve-se notar que T_COMMENT nem sempre é seguido de espaço em branco, Ele também pode ser seguido de T_CLOSE_TAG ou o fim do arquivo (end-of-file).

  • Nomes com agora são representados usando os tokens T_NAME_QUALIFIED (Foo\Bar), T_NAME_FULLY_QUALIFIED (\Foo\Bar) e T_NAME_RELATIVE (namespace\Foo\Bar). T_NS_SEPARATOR é usado apenas para separadores de namespace independentes, e só é sintaticamente válido em conjuncão com declarações de uso de grupo.

XMLReader

XMLReader::open() e XMLReader::xml() agora são métodos estáticos. Eles ainda podem ser chamados como métodos de instância, mas classes herdadas precisam declará-los como estáticos se elas sobrescrevem esses métodos.

XML-RPC

A extensão XML-RPC foi movida para PECL e não é mais parte da distribuição PHP.

Zip

ZipArchive::OPSYS_Z_CPM foi removida (esse nome era um erro de digitação). Em vez dela, use ZipArchive::OPSYS_CPM.

Zlib

Pacotes de teste para PHP no Windows

O executor de testes foi renomeado de run-test.php para run-tests.php, para coincidir com seu nome em php-src.

add a note add a note

User Contributed Notes 3 notes

up
18
retry, abort, fail
2 years ago
The change in string to int comparison mentioned above (e.g. '' == 0 now equates to false) has some other nasty consequences:

$a = '';

// php 8

if ( $a < 0 ) echo 'true'; // echos true
if ( $a < -1) echo 'true'; // echos true
if ( $a < -100 ) echo 'true'; // echos true

// php 7

if ( $a < 0 ) echo 'true'; // no output
if ( $a < -1) echo 'true'; // no output
if ( $a < -100 ) echo 'true'; // no output

So in a situation where you may have a web form input and expected an empty value to equate to 0, watch out not only for == 0, != 0, and <= 0 comparisons, but ALL < or <= comparisons to negative integers.
up
2
aphpguy at galaxy dot za dot net
1 year ago
If you have older projects that break with PHP7 to 8 migration due to the loose comparison issue:

i.e. if ($a == 0) different behaviour between PHP 7 and PHP 8
(for case like $a = "" or $a = "123foo" and other cases listed at top)

replace in old code:

if ($a == 0) { .. } 

with

if (cmp_eq($a, $b)) { .. }

Tested with a wide range of scenarios, even against arrays, booleans, file handles, pipe handles, objects, scalars and numbers.

So old code still behave like before. 
Then both PHP8.x and older PHP up to ver 7.x will give the exact same boolean true or false output for loose comparisons.

function cmp_eq($a, $b) {
// If both $a and $b are of type strings, compare them as strings
if (is_string($a) && is_string($b)) { return $a == $b; } // may not be === because php says '42' equals '042' true yet '42' === '042' is false.

// If both $a and $b are numeric strings, compare them as numbers
if (is_numeric($a) && is_numeric($b)) { return $a == $b; }

// If $a is an empty string and $b is 0, or vice versa, return true
if (($a === '' && $b === 0) || ($a === 0 && $b === '')) { return true; }

// If $a is a non-numeric string and $b is 0, or vice versa, return true
if ((is_string($a) && ($a !== '') && ($b === 0)) || (($a === 0) && is_string($b) && ($b !== ''))) {
return true;
}
// special case '123abc' == 123 .. php 7 casts 123abc to 123, then 123 == 123 results in true. lets mimic that.
if ((is_string($a) && ($a !== '') && (is_numeric($b)) && ((bool)$b))) {
$number = filter_var($a, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); //"-234.56xyz"
return $number == $b;
}
if (is_numeric($a) && ((bool)$a) && is_string($b) && ($b !== '')) {
$number = filter_var($b, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); //"-234.56xyz"
return $a == $number;
}

// If $a is a number and $b is a non-numeric string, cast $a to string and compare
if (is_numeric($a) && is_string($b)) { return strval($a) == $b; }

// If $b is a number and $a is a non-numeric string, cast $b to string and compare
if (is_string($a) && is_numeric($b)) { return $a == strval($b); }

// If $a and $b are both non-numeric strings, compare them directly, we should return true if they are the same
return $a == $b;
} // end func cmp_eq

Note: the better way would be to port code to PHP 8, use strict variable typing and rather make use of the === and !== operators.

But in some cases having lots of old code to quickly patch, this might help.
up
-3
1035041238 at qq dot com
2 years ago
In PHP 8, an empty string is less than any number, an English letter is always bigger than any number.

More interesting are the punctuation marks and non-word characters, some bigger than numbers, some smaller than numbers

$string = '`~!@#$%^&*()-_=+[]{};:\'"\\|,.<>/?';

$number = 999999999999;

$str_len = strlen($string);

$bigger = $smaller = $equal = [];
for ( $i = 0; $i < $str_len; ++$i ) {
    if ( $string[$i] > $number ) {
        $bigger[] = $string[$i];
    } elseif ( $string[$i] < $number ) {
        $smaller[] = $string[$i];
    } else {
        $equal[] = $string[$i];
    }
}

var_dump( $bigger ); //['`', '~', '@', '^', '_', '=', '[', ']', '{', '}', ';', ':', '\', '|', '<', '>', '?']
var_dump( $smaller); //['!', '#', '$', '%', '&', '*', '(', ')', '-', '+', ''', '"', ',', '.', '/']
var_dump( $equal); //[]
To Top