Desenvolvimento

PHP 8.4 e 8.5 no Magento: o deprecated de nullable implícito

Nada quebra hoje, mas o aviso é emitido em tempo de compilação — ou seja, em todo arquivo que carrega. E o PHP 9 vai transformar isso em erro de verdade.

Por Roger Takemiya · Publicado em · 5 min de leitura

Você atualiza a stack, sobe para PHP 8.4 e o log de erro do PHP começa a crescer de minuto em minuto com a mesma linha repetida centenas de vezes:

Deprecated: Implicitly marking parameter $context as nullable is deprecated, the explicit nullable type must be used instead

A loja funciona, nada dá 500, e é justamente por isso que muita gente ignora. Só que ignorar tem prazo de validade.

O que mudou no PHP 8.4

A RFC Deprecate Implicitly Nullable Parameter Types foi aprovada e entrou no PHP 8.4. Ela mira exatamente esta assinatura:

function foo(T $var = null) {}

O valor padrão null fazia o PHP aceitar null naquele parâmetro sem você declarar. Continua aceitando — mas agora avisa. A correção é escrever o que sempre foi verdade:

// antes
public function __construct(LoggerInterface $logger = null) {}

// depois
public function __construct(?LoggerInterface $logger = null) {}

Com union type, o equivalente é acrescentar |null: string|int|null $x = null.

Dois detalhes que mudam o tamanho do problema. Primeiro, a RFC diz claramente que o suporte será removido no PHP 9: hoje é aviso, depois vira erro. Segundo, e é o que explica o volume no log, o aviso é emitido em tempo de compilação. Não é só quando a função é chamada — é toda vez que o arquivo é compilado. Em servidor com OPcache frio ou com validate_timestamps ligado, isso é muito log.

Onde isso pega no Magento

Primeiro, o calendário. Segundo a tabela de requisitos da Adobe, o 2.4.8 roda em PHP 8.4 e 8.3, e o 2.4.9 — lançado em 22 de maio de 2026 — pede PHP 8.5. Ou seja: quem está atualizando agora vai encarar isso de qualquer jeito.

Segundo, o padrão de código que todo mundo aprendeu a escrever no Magento. Quando você precisa injetar uma dependência nova numa classe que já existe sem quebrar quem estende ela, a receita é sempre a mesma: argumento novo no fim do construtor, opcional, com = null, e o ObjectManager::getInstance() lá dentro como plano B.

public function __construct(
    Context $context,
    ProductRepositoryInterface $productRepository,
    Json $serializer = null
) {
    $this->serializer = $serializer ?: ObjectManager::getInstance()->get(Json::class);
}

Esse Json $serializer = null é exatamente o caso da RFC. Como a prática é antiga e universal, módulo de terceiro escrito entre 2017 e 2023 costuma ter dezenas de ocorrências. Some o vendor/ inteiro e você entende o tamanho do log.

Não confunda com $x = null em parâmetro sem tipo. function foo($var = null) não tem tipo declarado, então não dispara nada. O aviso só vale para parâmetro tipado com padrão nulo.

Corrija em massa, sem revisar arquivo por arquivo

O PHP-CS-Fixer tem uma regra que faz exatamente essa troca, e a documentação a classifica como non-risky — ela só alinha a declaração com o valor padrão, sem mudar comportamento.

composer require --dev friendsofphp/php-cs-fixer

Antes de escrever qualquer coisa, veja o estrago em modo seco:

vendor/bin/php-cs-fixer fix app/code \
  --rules=nullable_type_declaration_for_default_null_value \
  --dry-run --diff

Duas coisas importantes nesse comando. Passar --rules com uma regra só faz o Fixer aplicar apenas ela — sem isso ele reformata indentação, aspas e imports do seu módulo inteiro, e aí o diff vira um monstro que ninguém revisa. E aponte para app/code, nunca para vendor/: código de terceiro você não altera no lugar, senão o próximo composer update apaga tudo.

Gostou do diff? Tire o --dry-run:

vendor/bin/php-cs-fixer fix app/code --rules=nullable_type_declaration_for_default_null_value

Quem já usa Rector no projeto tem o equivalente na regra ExplicitNullableParamTypeRector, que faz parte do conjunto de PHP 8.4 dele. Tanto faz a ferramenta; o que não vale é sair editando na mão.

Depois de corrigir

Três passos que eu não pulo:

  • Limpe o código gerado. Interceptor e factory em generated/code são compilados igual a qualquer PHP. Rode rm -rf generated/* e php bin/magento setup:di:compile depois da correção.
  • Rode os testes. A troca é segura no papel, mas o diff pode ter tocado em arquivo que você nem lembrava que existia. Se o módulo tem teste unitário, é a hora.
  • Não silencie. Tirar E_DEPRECATED do error_reporting resolve o log e não resolve o problema — no PHP 9 o mesmo código para de compilar.

Para o que veio do vendor/, a saída é outra: abra issue ou pull request no repositório do módulo, ou aplique um patch versionado com cweagans/composer-patches. Se o fornecedor não responde há dois anos, isso já é resposta sobre continuar usando aquele módulo — assunto que eu trato no guia de desenvolvimento de módulos.

E aproveite a passagem: se você mesmo escreve módulo, pare de adicionar dependência nova com = null por reflexo. Em código novo, declare ?Tipo desde o começo e você não paga essa conta de novo.

Perguntas rápidas

Isso pode derrubar minha loja hoje?

Não. É um aviso, o código continua rodando exatamente igual. Os efeitos reais são log gigante, disco enchendo e pipeline de CI que trata deprecated como erro falhando. O prazo é o PHP 9, quando a construção deixa de ser aceita.

Preciso corrigir isso antes de atualizar para o 2.4.9?

Não é bloqueio para atualizar, mas é bom fazer junto. Como o 2.4.9 pede PHP 8.5, você vai passar por essa faixa de versão de qualquer forma, e é bem mais barato rodar o fixer antes do que caçar log depois que a loja já está no ar.

O PHP-CS-Fixer vai bagunçar meu código?

Só se você deixar. Passando --rules com uma única regra, ele altera apenas os parâmetros com padrão nulo. Rode primeiro com --dry-run e --diff, confira o resultado e só então aplique.

Pra conferir na fonte

  1. PHP RFC: Deprecate Implicitly Nullable Parameter Types — php.net
  2. Rule nullable_type_declaration_for_default_null_value — PHP-CS-Fixer
  3. System requirements — Adobe Experience League
  4. Magento Open Source 2.4.9 release notes — Adobe Experience League

php módulo upgrade

Precisa de um orçamento? Ficarei feliz em ajudar. Clique Aqui