Modernizador PHP Legado → PHP 8.3/8.4

Actualización in situ de bases de código PHP 5.x/7.x (CMS personalizados, TemplatePower, mysql_*, ereg, etiquetas cortas, constructores PHP4) para ejecutarse en PHP 8.3/8.4 y desplegar sin Docker mediante configuración .env y deploy.sh con FTP/rsync.

¿Qué es 8.4?

Este skill automatiza la migración de proyectos PHP heredados (escritos para PHP 5.x/7.x) a PHP 8.3/8.4, sin necesidad de reescribir completamente la aplicación. Es ideal para modernizar CMS antiguos, sitios construidos con TemplatePower, o cualquier proyecto que use funciones obsoletas como mysql_*, ereg, etiquetas cortas (<?), constructores al estilo PHP4, o claves de array sin comillas. El skill proporciona un conjunto completo de scripts y plantillas: un shim de compatibilidad que emula funciones antiguas con reemplazos modernos (por ejemplo, mysql_* → mysqli), correctores tokenizados para problemas de sintaxis (como claves bareword o variables variables), un verificador de firmas de métodos para LSP, y un script de despliegue (FTP o rsync) que permite desplegar la aplicación modernizada en hosting compartido (cPanel/Plesk) sin Docker. Todo el proceso está documentado paso a paso, incluyendo reglas de seguridad, configuración de .env, y una lista de verificación para asegurar que el sitio funcione correctamente después de la migración. El skill es directamente utilizable con Claude Code, Cursor, Codex y otros asistentes de IA que soporten herramientas de desarrollo.

Compatible con~Claude Code~Codex CLI~Cursor✓OpenCode
npx skills add https://github.com/dbravoan/opencode-skills/tree/HEAD/skills/legacy-php8-modernizer

Installed? Explore more Investigación y análisis de datos skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

¿Qué hace 8.4?

Cuándo usarme

Usa este skill cuando un proyecto PHP heredado (típicamente un CMS personalizado escrito para PHP 5.x) deba:

  • ejecutarse en PHP 8.3 / 8.4 sin una reescritura completa, y/o
  • ser desplegado en hosting compartido (cPanel/Plesk) mediante FTP, sin Docker.

Síntomas típicos: mysql_*, ereg/eregi, etiquetas cortas <?, constructores estilo PHP4, claves de array sin comillas ($row[Id]), $$var['key'], sizeof(null), dump MyISAM, plantillas TemplatePower, credenciales en texto plano en config/defines*.php.

Lo que incluye este skill

RecursoPropósito
scripts/compat.phpShim: mysql_*→mysqli, ereg*/split→preg, userErrorHandler
scripts/fix_barewords.phpCorrección tokenizada de claves bareword en arrays
scripts/fix_variable_variables.phpCorrige la rotura de sintaxis de variable variable $$var['key'] en PHP 8
scripts/check_signatures.phpVerificador estático de firmas de métodos (LSP)
scripts/lint-all.shBarrido php -l
scripts/smoke-test.shPrueba de humo HTTP sobre una lista de URLs
templates/defines.phpCargador de .env + constantes de base de datos (funciona con y sin Docker)
templates/env.examplePlantilla .env (DB_* + FTP_*)
templates/htaccess.htaccess moderno para Apache/PHP-FPM
templates/user.iniSobreescrituras de PHP-FPM para hosting compartido
templates/timthumb.phpGenerador seguro de miniaturas GD (reemplaza TimThumb vulnerable)
deploy/deploy.shDespliegue por FTP o rsync; excluye archivos de desarrollo; escribe .env remoto

Reglas de oro

  1. Seguridad primero: git init + commit de referencia antes de tocar nada. Haz una copia de seguridad de la base de datos.
  2. Desbloquear antes de refactorizar: el shim hace que toda la base de código funcione de inmediato.
  3. Una capa central de base de datos: intercambia/limita dbClass primero; el shim cubre las llamadas mysql_* sin procesar.
  4. Seguridad temprana: elimina herramientas peligrosas y TimThumb tan pronto como el sitio se renderice.
  5. Verificar continuamente: php -l después de cada lote, luego prueba de humo en cada URL.

Procedimiento

0. Línea base

git init -q && git add -A && git commit -qm "baseline: legacy PHP"
find . -name '*.php' -not -path './node_modules/*' | wc -l

Guarda una lista de URLs públicas reales (desde la base de datos/mapa del sitio) para scripts/smoke-test.sh.

1. Instalar el shim de compatibilidad

  • Copia scripts/compat.php a, por ejemplo, includes/compat.php.
  • Cárgalo al principio del bootstrap, antes de cualquier código heredado:
    include_once(__DIR__.'/../includes/compat.php');
    
  • Proporciona mysql_*, ereg/eregi/ereg_replace/eregi_replace/split, mysqli_report(MYSQLI_REPORT_OFF) (los errores SQL devuelven false en lugar de lanzar una excepción), y userErrorHandler() (suprime los antiguos E_NOTICE de PHP 5 como "undefined index/variable").
  • Registra el manejador una vez:
    if (function_exists('userErrorHandler')) set_error_handler('userErrorHandler');
    

2. Correcciones mecánicas (scripts)

php scripts/fix_barewords.php            # prueba en seco
php scripts/fix_barewords.php --apply
php scripts/fix_variable_variables.php   # prueba en seco
php scripts/fix_variable_variables.php --apply
scripts/lint-all.sh

Luego corrige lo que aún reporte el lint:

  • Etiquetas cortas: <? → <?php (busca con grep <\(?!php|=|xml\)).
  • Constructores PHP4: function NombreClase() → function __construct().
  • Acceso a cadenas con llaves: $s{0} → $s[0].
  • break sueltos fuera de bucles/switches (fatal en PHP 8).
  • Variables variables en ${...}: entrecomilla las claves bareword / usa ${$var['k']}.

3. Firmas, estática y seguridad nula

php scripts/check_signatures.php

Para cada MISMATCH, agrega parámetros por defecto al método hijo (ej. $tabla = null). Luego corrige en tiempo de ejecución según aparezcan errores fatales:

ErrorCorrección
ArgumentCountError: too few argumentsasigna valores por defecto a parámetros finales
$this en método estáticousa self::/static:: o pasa el contexto de la aplicación
method_exists(null, ...)is_object($x) && method_exists($x, ...)
Cannot access offset of type string on stringreordena is_array($x) antes de $x['k']
Undefined constant "X"entrecomilla claves 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. Ejecutar contra la base de datos real e iterar

Apunta la configuración a la base de datos, luego solicita cada URL. Corrige un error fatal por prueba hasta que scripts/smoke-test.sh reporte cero fallos y el registro no tenga advertencias.

5. Seguridad (hacerlo temprano)

  • Reemplaza TimThumb con templates/timthumb.php.
  • Elimina scanner.php, chmod777.php, info.php, scripts de depuración sueltos.
  • Configura .htaccess para denegar .env, .git, config/defines.php, archivos con punto.
  • Rota las contraseñas de base de datos comprometidas; mueve secretos a .env.
  • Recomienda tokens CSRF, CSP/HSTS, limitación de tasa, sentencias preparadas.

6. Configuración + despliegue

  • Usa templates/defines.php (cargador de .env) y templates/env.example.
  • Usa templates/htaccess y templates/user.ini.
  • Despliega con deploy/deploy.sh.

Sistema .env

config/defines.php carga .env desde la raíz del proyecto, con fallback a getenv() y finalmente valores predeterminados seguros. Esto mantiene Docker funcionando (mismas claves DB_*) mientras hace que el despliegue por FTP sea una edición de un solo archivo.

.env (nunca se sube al repositorio):

DB_HOST=localhost
DB_NAME=usuario_cpanel_termospa
DB_USER=usuario_cpanel_termospa
DB_PASS=super-secreto
DB_SUBDIRECTORIO=

Despliegue (sin Docker)

Lista de verificación para hosting compartido (cPanel/Plesk)

  1. PHP: selecciona 8.3 (o 8.1+); habilita mysqli, gd, mbstring, pdo_mysql.
  2. Base de datos: crea base de datos + usuario, importa el dump. Para MySQL 8:
    SET SESSION sql_mode='NO_ENGINE_SUBSTITUTION';
    
    Espera advertencias de utf8_spanish_ci → utf8mb3_spanish_ci (o ejecuta la migración a utf8mb4).
  3. Archivos: sube a public_html/ (excluye docker/, tools/, router.php, _DOCS/, .git/).
  4. Permisos: directorios 755, archivos 644; recursos/cache/, .cache/, upload/ escribibles (775/777).
  5. Configuración: crea el .env remoto (deploy.sh lo hace) y verifica las variables DB_*.
  6. Deniega el acceso a .env en .htaccess.

deploy.sh

./deploy.sh ftp          # lftp reverse mirror
./deploy.sh ftp --dry-run
./deploy.sh rsync        # rsync sobre SSH

Lee .env (FTP_HOST/USER/PASS/PATH/TLS, o SSH_*), prepara solo los archivos de tiempo de ejecución, escribe un .env solo remoto que contiene únicamente DB_* (para que las credenciales FTP nunca estén en el servidor), sube, e imprime los pasos de permisos y base de datos.


Lista de verificación de verificación

  • scripts/lint-all.sh → todo limpio
  • scripts/smoke-test.sh urls.txt → 0 fallos
  • las páginas de inicio / producto / proyecto / noticias / contacto se renderizan
  • /sitemap.xml y /rss devuelven XML válido
  • /imagenes/thumbnail/... devuelve una imagen (GD + reescritura)
  • /administracion/login/ carga; el inicio de sesión y un gestor de contenido funcionan
  • el formulario de contacto envía
  • la subida de imágenes del administrador escribe en upload/
  • no hay PHP Warning/Fatal en el registro de errores

Problemas que siempre aparecen

  • mysqli_query lanza una excepción en PHP 8.1+ por defecto; llama a mysqli_report(MYSQLI_REPORT_OFF) para que or die() / if($q=...) heredado siga funcionando.
  • php_flag / php_value en .htaccess causa HTTP 500 con PHP-FPM — usa .user.ini.
  • La sintaxis de variable uniforme de PHP 8 rompe silenciosamente $$var['key'] (escribe en la variable incorrecta) — ejecuta fix_variable_variables.php.
  • Las rutas relativas en include() se resuelven contra el directorio del script/CWD; prefiere __DIR__.
  • Eliminado en PHP 8: mysql_*, ereg*, split, create_function, each, magic quotes.
  • OPcache almacena en caché archivos antiguos: reinicia FPM/Apache después de editar.
  • UTF-8: SET NAMES utf8mb4; prefiere InnoDB + utf8mb4_unicode_ci para trabajo nuevo.

Proyectos hermanos

Estos proyectos CMS comparten la misma arquitectura. Ejecuta el mismo procedimiento, ajustando solo la ruta del bootstrap y el destino de la reescritura de miniaturas. Copia scripts/ dentro de tools/ del proyecto destino, ejecuta desde la raíz del proyecto.

Skills relacionados