Modernizador PHP Legado → PHP 8.3/8.4
Quando usar
Use este skill quando um projeto PHP legado (tipicamente um CMS customizado escrito para PHP 5.x) precisar:
- rodar em PHP 8.3 / 8.4 sem reescrita completa, e/ou
- ser implantado em hospedagem compartilhada (cPanel/Plesk) via FTP, sem Docker.
Sintomas típicos: mysql_*, ereg/eregi, tags curtas <?, construtores no estilo PHP4,
chaves de array bareword ($row[Id]), $$var['key'], sizeof(null), dump MyISAM,
templates TemplatePower, credenciais em texto puro em config/defines*.php.
O que este skill fornece
| Recurso | Propósito |
|---|---|
scripts/compat.php | Shim: mysql_*→mysqli, ereg*/split→preg, userErrorHandler |
scripts/fix_barewords.php | Correção segura via tokenizer de chaves de array bareword |
scripts/fix_variable_variables.php | Corrige quebra de sintaxe uniforme de variáveis do PHP 8 ($$var['key']) |
scripts/check_signatures.php | Verificador estático de assinatura de métodos (LSP) |
scripts/lint-all.sh | Varredura php -l |
scripts/smoke-test.sh | Teste de fumaça HTTP em uma lista de URLs |
templates/defines.php | Carregador .env + constantes DB (funciona com e sem Docker) |
templates/env.example | Template .env (DB_* + FTP_*) |
templates/htaccess | .htaccess moderno para Apache/PHP-FPM |
templates/user.ini | Overrides PHP-FPM para hospedagem compartilhada |
templates/timthumb.php | Gerador seguro de thumbnails GD (substitui TimThumb vulnerável) |
deploy/deploy.sh | Implantação via FTP ou rsync; exclui arquivos de dev; escreve .env remoto |
Regras de ouro
- Segurança primeiro:
git init+ commit de baseline antes de tocar em qualquer coisa. Faça backup do banco. - Desbloqueie antes de refatorar: o shim faz todo o codebase rodar imediatamente.
- Uma camada central de banco: troque/limite
dbClassprimeiro; o shim cobre chamadasmysql_*diretas. - Segurança cedo: remova ferramentas perigosas e TimThumb assim que o site renderizar.
- Verifique continuamente:
php -lapós cada lote, depois teste de fumaça em cada URL.
Procedimento
0. Baseline
git init -q && git add -A && git commit -qm "baseline: legado PHP"
find . -name '*.php' -not -path './node_modules/*' | wc -l
Salve uma lista de URLs públicas reais (do banco/sitemap) para scripts/smoke-test.sh.
1. Instale o shim de compatibilidade
- Copie
scripts/compat.phppara, ex.,includes/compat.php. - Carregue-o bem no início do bootstrap, antes de qualquer código legado:
include_once(__DIR__.'/../includes/compat.php'); - Ele fornece
mysql_*,ereg/eregi/ereg_replace/eregi_replace/split,mysqli_report(MYSQLI_REPORT_OFF)(erros SQL retornamfalseem vez de lançar exceção), euserErrorHandler()(suprime os antigos E_NOTICE do PHP 5 como "undefined index/variable"). - Registre o handler uma vez:
if (function_exists('userErrorHandler')) set_error_handler('userErrorHandler');
2. Correções mecânicas (scripts)
php scripts/fix_barewords.php # simulação
php scripts/fix_barewords.php --apply
php scripts/fix_variable_variables.php # simulação
php scripts/fix_variable_variables.php --apply
scripts/lint-all.sh
Em seguida, corrija o que o lint ainda reportar:
- Tags curtas:
<?→<?php(grep<\(?!php|=|xml)). - Construtores PHP4:
function ClassName()→function __construct(). - Offsets de string com chaves:
$s{0}→$s[0]. breaksolto fora de loops/switch (fatal no PHP 8).- Variáveis variáveis em
${...}: coloque aspas nas barewords / use${$var['k']}.
3. Assinaturas, estático e segurança contra null
php scripts/check_signatures.php
Para cada MISMATCH, adicione parâmetros padrão ao método filho (ex., $tabla = null).
Depois corrija em tempo de execução conforme os fatais aparecerem:
| Erro | Correção |
|---|---|
ArgumentCountError: too few arguments | dê padrões aos parâmetros finais |
$this em método estático | use self::/static:: ou passe o contexto da aplicação |
method_exists(null, ...) | is_object($x) && method_exists($x, ...) |
Cannot access offset of type string on string | coloque is_array($x) antes de $x['k'] |
Undefined constant "X" | coloque aspas nas chaves bareword / constantes |
sizeof/count/array_keys(null) | is_array($x) ? ... : ..., (array)$x |
foreach(null) | foreach ((array)$x as ...) |
Accessing static property X as non static | $this->prop → self::$prop |
4. Execute contra o banco real e itere
Aponte a config para o banco, então solicite cada URL. Corrija um fatal por teste até que
scripts/smoke-test.sh reporte zero falhas e o log não tenha nenhum warning.
5. Segurança (faça cedo)
- Substitua TimThumb por
templates/timthumb.php. - Delete
scanner.php,chmod777.php,info.php, scripts de debug avulsos. - Faça o
.htaccessnegar.env,.git,config/defines.php, dotfiles. - Rotacione senhas de banco commitadas; mova segredos para
.env. - Recomende tokens CSRF, CSP/HSTS, rate limiting, prepared statements.
6. Config + implantação
- Use
templates/defines.php(carregador.env) etemplates/env.example. - Use
templates/htaccessetemplates/user.ini. - Implante com
deploy/deploy.sh.
Sistema .env
config/defines.php carrega .env da raiz do projeto, caindo para getenv()
e finalmente para defaults seguros. Isso mantém o Docker funcionando (mesmas chaves DB_*) enquanto torna a implantação FTP uma edição de um arquivo.
.env (nunca commitado):
DB_HOST=localhost
DB_NAME=cpaneluser_termospa
DB_USER=cpaneluser_termospa
DB_PASS=super-secret
DB_SUBDIRECTORIO=
Implantação (sem Docker)
Checklist para hospedagem compartilhada (cPanel/Plesk)
- PHP: selecione 8.3 (ou 8.1+); habilite
mysqli,gd,mbstring,pdo_mysql. - Banco: crie banco + usuário, importe o dump. Para MySQL 8:
Espere warningsSET SESSION sql_mode='NO_ENGINE_SUBSTITUTION';utf8_spanish_ci→utf8mb3_spanish_ci(ou execute a migração utf8mb4). - Arquivos: faça upload em
public_html/(excluadocker/,tools/,router.php,_DOCS/,.git/). - Permissões: diretórios
755, arquivos644;recursos/cache/,.cache/,upload/graváveis (775/777). - Config: crie o
.envremoto (deploy.sh faz isso) e verifiqueDB_*. - Negue acesso a
.envno.htaccess.
deploy.sh
./deploy.sh ftp # lftp reverse mirror
./deploy.sh ftp --dry-run
./deploy.sh rsync # rsync via SSH
Ele lê .env (FTP_HOST/USER/PASS/PATH/TLS, ou SSH_*), prepara apenas os arquivos de runtime,
escreve um .env apenas remoto contendo só DB_* (para que credenciais FTP nunca fiquem
no servidor), faz upload e imprime os passos de permissão/banco.
Checklist de verificação
-
scripts/lint-all.sh→ tudo limpo -
scripts/smoke-test.sh urls.txt→ 0 falhas - home / produto / projeto / notícia / contato renderizam
-
/sitemap.xmle/rssretornam XML válido -
/imagenes/thumbnail/...retorna uma imagem (GD + rewrite) -
/administracion/login/carrega; login + um gerenciador de conteúdo funciona - formulário de contato envia
- upload de imagem no admin grava em
upload/ - nenhum
PHP Warning/Fatalno log de erros
Pegadinhas que sempre pegam
mysqli_querylança exceção por padrão no PHP 8.1+; chamemysqli_report(MYSQLI_REPORT_OFF)para queor die()/if($q=...)legados continuem funcionando.php_flag/php_valueno.htaccesscausam HTTP 500 sob PHP-FPM — use.user.ini.- A sintaxe uniforme de variáveis do PHP 8 quebra silenciosamente
$$var['key'](escreve na variável errada) — executefix_variable_variables.php. include()com caminhos relativos resolve em relação ao diretório do script/CWD; prefira__DIR__.- Removidos no PHP 8:
mysql_*,ereg*,split,create_function,each, magic quotes. - OPcache armazena em cache arquivos antigos: reinicie FPM/Apache após edições.
- UTF-8:
SET NAMES utf8mb4; prefira InnoDB +utf8mb4_unicode_cipara novos trabalhos.
Projetos irmãos
Estes projetos CMS compartilham a mesma arquitetura. Execute o mesmo procedimento, ajustando apenas
o caminho do bootstrap e o alvo do rewrite de thumbnails. Copie scripts/ para o diretório
tools/ do alvo e execute a partir da raiz do projeto.