CodeIgniter 3 PHP 8.3: os erros fatais que aparecem logo no boot

Subi um sistema em CodeIgniter 3.1.13 pro PHP 8.3 e ele morreu no primeiro request: Call to undefined function each(), com o trace terminando em system/core/Common.php. Esse arquivo não é o culpado. É nele que mora o _exception_handler, que o system/core/CodeIgniter.php pendura no boot com set_exception_handler(), então todo fatal passa por ali. Quem interessa é a linha de cima do trace, dentro de application/.

Os três pontos que quebram

O each() e o create_function() saíram no PHP 8.0 e não têm substituto automático: o primeiro vira foreach, o segundo vira closure. O terceiro é o traiçoeiro, porque não aparece no boot: desde o PHP 8.1 o mysqli reporta falha por exceção (MYSQLI_REPORT_ERROR e MYSQLI_REPORT_STRICT vêm ligados por padrão). O driver em system/database/drivers/mysqli/mysqli_driver.php devolve FALSE pro DB_driver.php tratar, e é esse contrato que some: a primeira query ruim estoura mysqli_sql_exception antes de qualquer tratamento do framework.

grep -rn --include='*.php' -E 'beach(|bcreate_function(' application/ system/

# varredura completa; o stable 9.3.4 é de 2019 e não conhece o 8.3
composer require --dev phpcompatibility/php-compatibility:dev-develop 
  dealerdirect/phpcodesniffer-composer-installer
vendor/bin/phpcs -p application/ --standard=PHPCompatibility 
  --runtime-set testVersion 8.3

O remendo que segura o mysqli

// index.php, antes do require_once BASEPATH.'core/CodeIgniter.php'
mysqli_report(MYSQLI_REPORT_OFF);

Isso devolve o comportamento antigo e faz o CI voltar a tratar erro de banco como ele sabe. É remendo: esconde a exceção, não conserta a query. Deixe o db_debug ligado em homologação pra não perder o erro de vista. Argumento opcional declarado antes de obrigatório é só Deprecated desde o 8.0, não derruba nada, mas em library de terceiro isso enche o error.log a cada requisição.

A conta honesta: o 3.1.13 é de 2022 e não vai ganhar versão nova. Se o phpcs voltar com centenas de ocorrências espalhadas em libraries que ninguém mantém, remendar sai mais caro que reescrever o módulo crítico. Rode as duas varreduras em homologação com display_errors ligado e navegue nas telas que usam banco: o que não quebra no boot costuma quebrar na primeira consulta.

Dúvidas? Faça um comentário logo abaixo ou envie uma mensagem clicando aqui.

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *