2 visitas

Migrando de PHP puro a Laravel: Lecciones aprendidas y cómo lo hicimos sin romper producción

Hace unos meses, nuestro equipo enfrentó un gran desafío: migrar parte de un sistema heredado escrito en **PHP puro** a **Laravel**, sin afectar la producción y manteniendo la misma base de datos. Fue un proceso lleno de aprendizajes, y hoy quiero compartir cómo lo logramos, los errores que evitamos y las estrategias que nos funcionaron.

1. Mantener la base de datos sin cambios (al principio)

Uno de los mayores temores en una migración es modificar la estructura de la base de datos. Decidimos no tocar las tablas existentes y trabajar con los mismos esquemas, pero aprovechando Eloquent, el ORM de Laravel.

Ejemplo: Modelos con tablas heredadas

Supongamos que teníamos una tabla users con una estructura poco convencional:

CREATE TABLE users (
    user_id INT PRIMARY KEY,
    username VARCHAR(50),
    signup_date DATETIME,
    is_active TINYINT(1)
);

En Laravel, definimos el modelo respetando la estructura antigua:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model {
    protected $table = 'users';
    protected $primaryKey = 'user_id';
    public $timestamps = false;

    protected $casts = [
        'is_active' => 'boolean',
    ];

    protected $dates = [
        'signup_date',
    ];
}

Beneficio:

  • No hubo que modificar queries existentes en la aplicación legacy.
  • Pudimos migrar gradualmente las consultas a Eloquent.

2. Manejo de eventos con Triggers (para mantener consistencia)

Como el sistema legacy aún escribía en la base de datos, usamos triggers para sincronizar cambios importantes con el nuevo sistema.

Ejemplo: Trigger para registrar cambios en una tabla

Queríamos auditar cambios en la tabla orders sin modificar el código legacy:

DELIMITER //
CREATE TRIGGER after_order_update
AFTER UPDATE ON orders
FOR EACH ROW
BEGIN
    INSERT INTO order_audit_log (order_id, changed_by, old_status, new_status)
    VALUES (NEW.id, CURRENT_USER(), OLD.status, NEW.status);
END //
DELIMITER ;

¿Por qué?

  • Evitamos tener lógica duplicada en ambos sistemas.
  • Garantizamos que los logs se guarden incluso si el código legacy no los manejaba.

3. Comenzar con las entidades pequeñas (y menos críticas)

No migramos todo de golpe. Priorizamos módulos con bajo impacto en producción:

Módulo Complejidad Riesgo Beneficio Migración
Sistema de logs Baja Bajo Fácil de testear
Gestión de FAQs Media Medio Mejor rendimiento
Procesos de pago Alta Alto Postergado

Estrategia:

  1. Migrar lo sencillo primero para ganar confianza.
  2. Aprender del proceso antes de atacar partes críticas.

4. Un router para redirigir tráfico gradualmente

Para no sacar nunca la app de producción, implementamos un ruteador simple que decidía qué sistema usar según la ruta:

// En public/index.php (Laravel) y legacy/index.php (PHP puro)

$requestPath = $_SERVER['REQUEST_URI'];

if (str_starts_with($requestPath, '/new/')) {
    // Laravel maneja esta ruta
    require __DIR__ . '/../laravel/public/index.php';
} else {
    // El sistema legacy sigue respondiendo
    require __DIR__ . '/legacy/index.php';
}

Ventaja:

  • Los usuarios no notaron el cambio.
  • Pudimos migrar endpoints de uno en uno.

5. Testing automático: Reducción de bugs

El sistema legacy no tenía tests. Introdujimos PHPUnit y Pest para el nuevo código:

// Tests/Feature/UserTest.php
test('User model respects legacy schema', function () {
    $user = User::create([
        'user_id' => 999,
        'username' => 'testuser',
        'is_active' => 1,
    ]);

    $this->assertDatabaseHas('users', [
        'user_id' => 999,
        'is_active' => true,
    ]);
});

Resultado:

  • +80% menos bugs en el código migrado.
  • Confianza al refactorizar.

6. Comunicación en el equipo: Ajustes constantes

Usamos daily standups y un documento compartido para registrar:

  • Qué endpoints ya estaban migrados.
  • Quién estaba trabajando en qué.
  • Problemas encontrados y soluciones.

Conclusión: Valió la pena

  • Menos errores en producción.
  • Nuevas features se implementaron más rápido.
  • El equipo aprendió buenas prácticas (ORM, testing, MVC).

¿Estás pensando en migrar un sistema legacy? Empieza pequeño, mantén la base de datos estable y no subestimes el poder de los tests.

¿Has pasado por una migración similar? ¡Comparte tus aprendizajes en los comentarios! 👇

#PHP #Laravel #LegacyCode #Refactoring #WebDevelopment

Migrando de PHP puro a Laravel: Lecciones aprendidas y cómo lo hicimos sin romper producción
28 July 2025

Me dedico a crear soluciones web eficientes y a compartir mi conocimiento con la comunidad de desarrolladores.

Alejandro Leone
Backend Developer