Skip to main content
Si tu paquete genera metadatos por adelantado, pedir a los usuarios que añadan un comando específico a su proceso de despliegue hace fácil que se olvide ejecutarlo al actualizar. Con ServiceProvider::optimizes() puedes incorporar los comandos de generación y eliminación a los comandos optimize y optimize:clear de Laravel. Esta página parte de los fundamentos del desarrollo de paquetes y revisa la implementación de Laravel Framework v13.35.0. No trata el formato de los archivos de caché, sino el contrato de registro y de operación.

Separar el registro de comandos del registro de tareas

commands() registra las clases de comando que se pueden invocar desde Artisan. optimizes() es un proceso distinto que registra como tareas de optimización nombres de comandos que ya son ejecutables. Si solo llamas al segundo, las clases de comando no quedan registradas. El siguiente ejemplo asume que el paquete ya implementa CacheMetadataCommand y ClearMetadataCommand, y que sus $signature son courier:cache y courier:clear-cache, respectivamente.
Todos los argumentos de optimizes() son nullable, así que puedes registrar solo la generación o solo la eliminación. Aun así, indica siempre a los usuarios con qué procedimiento se invalida la caché generada.

La clave de registro también es un contrato con el usuario

ServiceProvider guarda los comandos de generación en el array estático $optimizeCommands y los de eliminación en $optimizeClearCommands. En ambos casos, key se usa como clave del array. Si omites key, el nombre se genera a partir del nombre de clase del provider. Por ejemplo, CourierServiceProvider da courier. Como solo se usa el nombre de la clase, pueden producirse colisiones incluso con providers del mismo nombre en otros espacios de nombres. Si vuelves a registrar la misma clave, el comando de ese lado se sobrescribe con el valor posterior. Si quieres registrar varias tareas, usa claves distintas. Evita también las claves de las tareas estándar de Laravel, como config o routes, porque al combinar las tareas estándar con las del paquete, las claves de texto iguales también se sobrescriben.
Indica explícitamente una clave que identifique el paquete, como acme-courier, y mantenla entre versiones. La clave se convierte en el nombre que se muestra para la tarea y también en el valor que los usuarios indican en --except.

Se ejecutan después de las tareas estándar

En la implementación revisada, ambos comandos expanden el array registrado por los paquetes sobre el array de tareas estándar y luego las invocan en orden. Si usas una clave que no colisiona, las tareas del paquete se añaden después de las estándar. Partiendo de este orden, el comando de generación no debe reconstruir otras cachés estándar, sino generar solo los datos que pertenecen al paquete. No uses optimizes() como API para controlar el orden de dependencias entre varios paquetes: si necesitas un orden estricto, enumera explícitamente los comandos específicos.
optimize:clear también incluye cache:clear, que elimina los datos del almacén de caché por defecto. Si solo quieres borrar la caché propia del paquete, ejecuta courier:clear-cache directamente. Diseña además el comando de eliminación del paquete para que no haga flush de todo el almacén compartido y elimine solo las claves o archivos que le pertenecen.

Excluir por clave o por nombre de comando

La opción --except de ambos comandos acepta valores separados por comas. Se eliminan los espacios al principio y al final de cada valor, y se excluyen las tareas cuya clave o nombre de comando coincida.
Los dos primeros excluyen la misma tarea de generación. El tercero excluye la tarea de eliminación del paquete y el cache:clear estándar. cache es la clave de la tarea, no un nombre propio del paquete. La exclusión solo afecta a esa ejecución. No es una configuración que desactive el registro del provider ni que elimine automáticamente una caché del paquete creada anteriormente.

Distinguir el FAIL de una tarea del código de salida del comando padre

OptimizeCommand y OptimizeClearCommand invocan cada tarea con callSilently() y pasan a la visualización de la tarea si el código de salida es 0. Como la salida normal de los comandos hijos no se muestra, para investigar la causa ejecuta directamente el comando específico. En Laravel v13.35.0, ninguno de los dos handle() devuelve como valor de retorno del padre el código distinto de cero que devuelva un comando hijo. Aunque se muestre FAIL en pantalla, el bucle continúa y, si no hay excepciones, el código de salida del comando padre es 0. En cambio, las excepciones lanzadas se vuelven a lanzar en el componente de visualización de tareas, así que no siguen el mismo comportamiento de continuar.
No des por hecho que la caché del paquete se generó correctamente solo porque php artisan optimize terminó con código de salida 0. Este comportamiento se basa en la implementación de la versión revisada, así que compruébalo también cuando actualices las versiones de Laravel compatibles.
Si la generación del paquete es un requisito obligatorio del despliegue, usa un procedimiento que permita comprobar directamente el código de salida del comando hijo. Por ejemplo, a continuación se excluye la tarea del paquete de la ejecución conjunta y se ejecuta directamente una sola vez después de las tareas estándar.
Este ejemplo refleja en el código de salida el fallo de courier:cache, pero no agrega las salidas distintas de cero de las tareas estándar. En despliegues que también necesiten detectar con rigor los fallos de las tareas estándar, ejecuta por separado los comandos necesarios y comprueba sus códigos de salida.

Diseño y verificación de una caché que resista las actualizaciones

Además del registro, define también las responsabilidades de los comandos y del lado que lee la caché.
  • La generación debe llevar al mismo estado a partir de la misma entrada aunque se ejecute repetidamente, y no debe activar datos incompletos si falla a mitad del proceso.
  • La eliminación debe completarse correctamente aunque no exista caché, y no debe borrar la configuración publicada ni los datos persistentes del usuario.
  • Un comando cuya generación falle debe informar del error y devolver un valor distinto de cero. El lado que lee tampoco debe tratar incondicionalmente como válida una caché dañada.
  • Si cambias el formato de la caché, indica a los usuarios que deben regenerarla y considera también reiniciar los procesos de larga duración.
Además de las pruebas del paquete, verifica lo siguiente en la aplicación que lo usa. Como los arrays de registro son estáticos, ten cuidado también con el estado de registro que se arrastra entre pruebas dentro del mismo proceso.

Páginas relacionadas

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

Repasa cómo se completan los valores de la configuración publicada y su relación con la reconstrucción de la caché de configuración.

Probar paquetes Laravel con Orchestra Testbench

Registra providers y comandos Artisan en el entorno de pruebas.

Fuentes primarias consultadas

Última modificación el 6 de octubre de 2026