Skip to main content
Para mantener a largo plazo un paquete que usa la base de datos, no basta con la instalación inicial: también necesitas un procedimiento para hacer llegar los cambios a los usuarios que ya tienen las tablas creadas. Diseña la publicación, la ejecución y el historial de ejecución de las migraciones como procesos separados. Esta página parte de los fundamentos del desarrollo de paquetes y analiza ServiceProvider, VendorPublishCommand y Migrator de Laravel 13. La implementación del framework que se toma como referencia es v13.34.0.

¿Copiar los archivos o cargarlos desde el paquete?

publishesMigrations() solo registra el origen y el destino de la copia como recursos publicables. Arrancar el provider no copia archivos ni ejecuta SQL. Por su parte, loadMigrationsFrom() registra una ruta de búsqueda en el Migrator. Con un migrate normal, los archivos de esa ruta también se incluyen, pero arrancar el provider por sí solo no los ejecuta. Si el diseño espera que el usuario ajuste nombres de tablas o columnas antes de ejecutar, la publicación es la opción candidata. Si el paquete gestiona el esquema y no se espera que el usuario edite los archivos, también puedes considerar la carga directa. Los dos ejemplos de provider siguientes son alternativas entre sí.
Evita un diseño que publique una migración y al mismo tiempo la cargue directamente. Si la marca de tiempo cambia al publicar, el origen y el destino se tratan como entradas distintas del historial de ejecución, y el mismo proceso de creación de tablas podría ejecutarse dos veces.

Implementar la publicación

Asigna una etiqueta propia del paquete para que el usuario pueda publicarlo por separado de otros recursos.
En la instalación inicial, copia los archivos indicando el provider y la etiqueta, revisa su contenido y después ejecútalos. Si indicas ambos, Laravel selecciona los recursos publicables de esa etiqueta que pertenecen a ese provider.

El cambio de marca de tiempo depende de la configuración

La documentación oficial describe que, al publicar, la marca de tiempo de la migración se actualiza a la fecha y hora actuales. Sin embargo, la implementación de ServiceProvider::publishesMigrations() solo añade el origen a los archivos cuya marca de tiempo se actualizará cuando database.migrations.update_date_on_publish está activado. El valor por defecto al leer esta configuración es false. En la aplicación estándar de Laravel 13, config/database.php incluye la siguiente configuración. En aplicaciones que heredan una estructura antigua, comprueba también que esta configuración exista.
Además, VendorPublishCommand reescribe la fecha cuando el archivo coincide con la ruta real de un origen registrado y el nombre de destino tiene el formato YYYY_MM_DD_HHMMSS_. Toma como base la hora de inicio del comando y suma un segundo por cada archivo afectado. Si el nombre no tiene este formato, ese proceso no le añade ninguna fecha.
La fecha posterior a la publicación del ejemplo es ilustrativa. El nombre real del archivo depende del momento en que se publique.
La actualización de la marca de tiempo depende tanto del registro en el paquete como de la configuración de la aplicación que lo usa. No cambies esta configuración de forma generalizada desde el provider del paquete; documenta el requisito en las instrucciones de instalación. Si se usa la caché de configuración, también hay que reconstruirla después de cambiar la configuración.

Volver a publicar no significa “añadir solo lo pendiente”

vendor:publish no consulta el historial de ejecución de la base de datos. Además, en el proceso de copia de v13.34.0, la comprobación de archivos existentes se hace sobre el destino antes del cambio de marca de tiempo. Incluso al publicar un directorio, primero comprueba si en el destino existe la misma ruta relativa que en el origen, y solo después reescribe la fecha. Por eso, si la fecha cambió en la primera publicación y en la aplicación no existe un archivo con el mismo nombre que el origen, volver a publicar la misma etiqueta puede añadir otro archivo con una fecha distinta. No des por hecho que, sin --force, siempre se evitan los duplicados.

Si una migración ya se ejecutó se decide por el nombre de archivo

Migrator::getMigrationName() devuelve el nombre base del archivo sin .php. Para determinar qué está pendiente, compara este nombre con el historial de ejecución. No decide en función de si el contenido PHP o el nombre de la tabla son iguales.
Son dos nombres de migración distintos. Aunque el primero ya se haya ejecutado, ese historial por sí solo no marca el segundo como ejecutado.
No vuelvas a ejecutar sin condiciones el comando de publicación de la instalación inicial en cada actualización del paquete, ni conviertas --force en el procedimiento estándar. Además de sobrescribir las ediciones de los archivos publicados, el cambio de fecha puede añadir procesos duplicados.

Implementar la carga directa

Si quieres que las migraciones del paquete se ejecuten tal cual, registra la ruta de búsqueda. Con este método no se añade ningún proceso que publique los mismos archivos.
loadMigrationsFrom() llama a path() cuando se resuelve el Migrator. Migrator::path() elimina las rutas de búsqueda duplicadas, y getMigrationFiles() indexa los archivos encontrados por nombre de migración y los ordena por ese nombre. Cuando el usuario actualiza el paquete, los archivos nuevos se incluyen en el siguiente migrate. No cambies el nombre de los archivos existentes y añade archivos nuevos para los nuevos cambios de esquema. Para evitar colisiones con otros paquetes, incluye también el nombre de la funcionalidad, como en create_courier_deliveries_table. Los archivos con el mismo nombre comparten la misma clave, así que no se ejecutan ambos de forma independiente.
Pasar de la publicación a la carga directa no es simplemente reescribir el provider. Si el historial de ejecución del usuario está registrado con los nombres asignados al publicar, no coincidirá con los nombres originales del paquete. Necesitas un procedimiento de transición que tenga en cuenta el historial de los usuarios existentes, los archivos publicados y los rollbacks.

Hacer llegar los cambios de esquema a los usuarios existentes

Por ejemplo, para añadir un número de seguimiento a la tabla de envíos, no edites el create_courier_deliveries_table ya publicado: añade un archivo nuevo para el cambio. Si editas la migración de creación existente, ese cambio no se ejecutará para los usuarios que ya la ejecutaron.
database/migrations/2026_10_02_000000_add_tracking_code_to_courier_deliveries_table.php
Como el ejemplo añade una columna a una tabla que ya tiene filas, aquí se define como nullable. Si necesitas hacerla obligatoria o rellenar datos, diseña por separado ese procedimiento y su orden de ejecución. Con la publicación, prepara un procedimiento de actualización que compare con los archivos ya publicados del usuario y entregue solo los archivos añadidos en esta versión. También puedes crear una etiqueta de publicación exclusiva para los archivos nuevos, pero si la actualización de fecha está activada, ejecutar esa etiqueta repetidamente requiere la misma precaución. No conviertas el procedimiento de actualización en volver a ejecutar la etiqueta de la instalación inicial. Con la carga directa, el código actualizado detecta los archivos nuevos. En ambos métodos, la existencia de los archivos no modifica la base de datos por sí sola, así que indica claramente en las notas de la versión que es necesario ejecutar las migraciones.

Qué comprobar antes de publicar una versión

Además de las pruebas de base de datos del paquete, comprueba los procedimientos de publicación y actualización en una aplicación que lo use. Cargar las migraciones directamente en las pruebas no equivale a verificar la publicación, en la que cambian los nombres de archivo.
  • Una instalación inicial en una base de datos vacía crea las tablas necesarias.
  • Al actualizar desde la base de datos y el historial de ejecución de una versión anterior, solo se aplican los cambios nuevos.
  • Revisa la lista de archivos tras repetir el mismo comando de publicación y comprueba que el procedimiento de actualización no genera duplicados.
  • El procedimiento tiene en cuenta si la actualización de fecha está activada o desactivada y si se editaron los archivos publicados.
  • Comprueba el rollback de las nuevas migraciones y su orden de ejecución respecto a las demás migraciones de la aplicación.

Páginas relacionadas

Migraciones

Repasa los fundamentos de la definición de esquemas, el historial de ejecución y los rollbacks.

Pruebas de paquetes

Prueba el service provider y la base de datos del paquete.

Fusión y caché de la configuración de paquetes

Revisa procedimientos de actualización que tienen en cuenta la configuración del usuario y la caché de configuración.

Gestión de la compatibilidad de versiones

Vincula los procedimientos de actualización y los cambios de compatibilidad con la política de versiones.

Fuentes primarias consultadas

Última modificación el 2 de octubre de 2026