Desarrollo de Paquetes
- Introducción
- Descubrimiento de Paquetes
- Proveedores de Servicios
- Recursos
- Comandos
- Activos Públicos
- Publicación de Grupos de Archivos
Introducción
Los paquetes son la forma principal de añadir funcionalidad a Laravel. Los paquetes pueden ser cualquier cosa, desde una gran manera de trabajar con fechas como Carbon o un paquete que te permite asociar archivos con modelos Eloquent como la Laravel Media Library de Spatie.
Hay diferentes tipos de paquetes. Algunos paquetes son independientes, lo que significa que funcionan con cualquier marco de PHP. Carbon y Pest son ejemplos de paquetes independientes. Cualquiera de estos paquetes se puede usar con Laravel requiriéndolos en tu archivo composer.json
.
Por otro lado, otros paquetes están específicamente destinados para su uso con Laravel. Estos paquetes pueden tener rutas, controladores, vistas y configuraciones específicamente diseñadas para mejorar una aplicación Laravel. Esta guía cubre principalmente el desarrollo de aquellos paquetes que son específicos de Laravel.
Una Nota sobre Facades
Al escribir una aplicación Laravel, generalmente no importa si usas contratos o fachadas, ya que ambos ofrecen niveles de testabilidad esencialmente equivalentes. Sin embargo, al escribir paquetes, tu paquete no tendrá típicamente acceso a todos los helpers de prueba de Laravel. Si deseas poder escribir tus pruebas de paquete como si el paquete estuviera instalado dentro de una aplicación Laravel típica, puedes usar el paquete Orchestral Testbench.
Descubrimiento de Paquetes
El archivo bootstrap/providers.php
de una aplicación Laravel contiene la lista de proveedores de servicios que deben ser cargados por Laravel. Sin embargo, en lugar de requerir que los usuarios añadan manualmente tu proveedor de servicios a la lista, puedes definir el proveedor en la sección extra
del archivo composer.json
de tu paquete para que sea cargado automáticamente por Laravel. Además de los proveedores de servicios, también puedes listar cualquier facade que te gustaría que fuera registrada:
"extra": { "laravel": { "providers": [ "Barryvdh\\Debugbar\\ServiceProvider" ], "aliases": { "Debugbar": "Barryvdh\\Debugbar\\Facade" } }},
Una vez que tu paquete ha sido configurado para el descubrimiento, Laravel registrará automáticamente sus proveedores de servicios y fábricas cuando se instale, creando una experiencia de instalación conveniente para los usuarios de tu paquete.
Optar por no participar en el descubrimiento de paquetes
Si eres el consumidor de un paquete y deseas desactivar el descubrimiento de paquetes para un paquete, puedes listar el nombre del paquete en la sección extra
del archivo composer.json
de tu aplicación:
"extra": { "laravel": { "dont-discover": [ "barryvdh/laravel-debugbar" ] }},
Puedes desactivar el descubrimiento de paquetes para todos los paquetes utilizando el carácter *
dentro de la directiva dont-discover
de tu aplicación:
"extra": { "laravel": { "dont-discover": [ "*" ] }},
Proveedores de Servicios
Los proveedores de servicios son el punto de conexión entre tu paquete y Laravel. Un proveedor de servicios es responsable de enlazar elementos en el contenedor de servicios de Laravel e informar a Laravel dónde cargar recursos del paquete como vistas, configuración y archivos de idioma.
Un proveedor de servicios extiende la clase Illuminate\Support\ServiceProvider
y contiene dos métodos: register
y boot
. La clase ServiceProvider
base se encuentra en el paquete Composer illuminate/support
, que debes añadir a las dependencias de tu propio paquete. Para aprender más sobre la estructura y el propósito de los proveedores de servicios, consulta su documentación.
Recursos
Configuración
Típicamente, necesitarás publicar el archivo de configuración de tu paquete en el directorio config
de la aplicación. Esto permitirá a los usuarios de tu paquete anular fácilmente tus opciones de configuración predeterminadas. Para permitir que tus archivos de configuración sean publicados, llama al método publishes
desde el método boot
de tu proveedor de servicios:
/** * Bootstrap any package services. */public function boot(): void{ $this->publishes([ __DIR__.'/../config/courier.php' => config_path('courier.php'), ]);}
Ahora, cuando los usuarios de tu paquete ejecuten el comando vendor:publish
de Laravel, tu archivo será copiado a la ubicación de publicación especificada. Una vez que tu configuración haya sido publicada, sus valores se pueden acceder como cualquier otro archivo de configuración:
$value = config('courier.option');
[!WARNING] No debes definir funciones anónimas en tus archivos de configuración. No pueden ser serializadas correctamente cuando los usuarios ejecutan el comando Artisan
config:cache
.
Configuración de Paquete Predeterminada
También puedes fusionar tu propio archivo de configuración de paquete con la copia publicada de la aplicación. Esto permitirá que tus usuarios definan solo las opciones que realmente desean sobrescribir en la copia publicada del archivo de configuración. Para fusionar los valores del archivo de configuración, utiliza el método mergeConfigFrom
dentro del método register
de tu proveedor de servicios.
El método mergeConfigFrom
acepta la ruta al archivo de configuración de tu paquete como su primer argumento y el nombre de la copia del archivo de configuración de la aplicación como su segundo argumento:
/** * Register any application services. */public function register(): void{ $this->mergeConfigFrom( __DIR__.'/../config/courier.php', 'courier' );}
[!WARNING] Este método solo fusiona el primer nivel del array de configuración. Si tus usuarios definen parcialmente un array de configuración multidimensional, las opciones faltantes no se fusionarán.
Rutas
Si tu paquete contiene rutas, puedes cargarlas utilizando el método loadRoutesFrom
. Este método determinará automáticamente si las rutas de la aplicación están en caché y no cargará tu archivo de rutas si las rutas ya han sido almacenadas en caché:
/** * Bootstrap any package services. */public function boot(): void{ $this->loadRoutesFrom(__DIR__.'/../routes/web.php');}
Migraciones
Si tu paquete contiene migraciones de base de datos, puedes usar el método publishesMigrations
para informar a Laravel que el directorio o archivo dado contiene migraciones. Cuando Laravel publique las migraciones, actualizará automáticamente la marca de tiempo dentro de su nombre de archivo para reflejar la fecha y hora actuales:
/** * Bootstrap any package services. */public function boot(): void{ $this->publishesMigrations([ __DIR__.'/../database/migrations' => database_path('migrations'), ]);}
Archivos de Idioma
Si tu paquete contiene archivos de idioma, puedes usar el método loadTranslationsFrom
para informar a Laravel cómo cargarlos. Por ejemplo, si tu paquete se llama courier
, deberías añadir lo siguiente al método boot
de tu proveedor de servicios:
/** * Bootstrap any package services. */public function boot(): void{ $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');}
Las líneas de traducción del paquete se hacen referencia utilizando la convención de sintaxis package::file.line
. Así que puedes cargar la línea welcome
del paquete courier
desde el archivo messages
de esta manera:
echo trans('courier::messages.welcome');
Puedes registrar archivos de traducción en JSON para tu paquete utilizando el método loadJsonTranslationsFrom
. Este método acepta la ruta al directorio que contiene los archivos de traducción JSON de tu paquete:
/** * Bootstrap any package services. */public function boot(): void{ $this->loadJsonTranslationsFrom(__DIR__.'/../lang');}
Publicando Archivos de Idioma
Si deseas publicar los archivos de idioma de tu paquete en el directorio lang/vendor
de la aplicación, puedes usar el método publishes
del proveedor de servicios. El método publishes
acepta un array de rutas de paquete y sus ubicaciones de publicación deseadas. Por ejemplo, para publicar los archivos de idioma para el paquete courier
, puedes hacer lo siguiente:
/** * Bootstrap any package services. */public function boot(): void{ $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier'); $this->publishes([ __DIR__.'/../lang' => $this->app->langPath('vendor/courier'), ]);}
Ahora, cuando los usuarios de tu paquete ejecuten el comando Artisan vendor:publish
de Laravel, los archivos de idioma de tu paquete se publicarán en la ubicación de publicación especificada.
Vistas
Para registrar las vistas de tu paquete con Laravel, necesitas indicar a Laravel dónde se encuentran las vistas. Puedes hacer esto utilizando el método loadViewsFrom
del proveedor de servicios. El método loadViewsFrom
acepta dos argumentos: la ruta a tus plantillas de vista y el nombre de tu paquete. Por ejemplo, si el nombre de tu paquete es courier
, agregarías lo siguiente al método boot
de tu proveedor de servicios:
/** * Bootstrap any package services. */public function boot(): void{ $this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');}
Las vistas del paquete se hacen referencia utilizando la convención de sintaxis package::view
. Así que, una vez que tu ruta de vista esté registrada en un proveedor de servicios, puedes cargar la vista dashboard
del paquete courier
de la siguiente manera:
Route::get('/dashboard', function () { return view('courier::dashboard');});
Sobrescribiendo Vistas de Paquetes
Cuando utilizas el método loadViewsFrom
, Laravel en realidad registra dos ubicaciones para tus vistas: el directorio resources/views/vendor
de la aplicación y el directorio que especificas. Así que, utilizando el paquete courier
como ejemplo, Laravel primero verificará si una versión personalizada de la vista ha sido colocada en el directorio resources/views/vendor/courier
por el desarrollador. Luego, si la vista no ha sido personalizada, Laravel buscará en el directorio de vistas del paquete que especificaste en tu llamada a loadViewsFrom
. Esto facilita que los usuarios del paquete personalicen o sobrescriban las vistas de tu paquete.
Publicando Vistas
Si deseas hacer que tus vistas estén disponibles para su publicación en el directorio resources/views/vendor
de la aplicación, puedes usar el método publishes
del proveedor de servicios. El método publishes
acepta un array de rutas de vista del paquete y sus ubicaciones de publicación deseadas:
/** * Bootstrap the package services. */public function boot(): void{ $this->loadViewsFrom(__DIR__.'/../resources/views', 'courier'); $this->publishes([ __DIR__.'/../resources/views' => resource_path('views/vendor/courier'), ]);}
Ahora, cuando los usuarios de tu paquete ejecuten el comando Artisan vendor:publish
de Laravel, las vistas de tu paquete se copiarán a la ubicación de publicación especificada.
Componentes de Vista
Si estás creando un paquete que utiliza componentes Blade o coloca componentes en directorios no convencionales, necesitarás registrar manualmente tu clase de componente y su alias de etiqueta HTML para que Laravel sepa dónde encontrar el componente. Generalmente, deberías registrar tus componentes en el método boot
del proveedor de servicios de tu paquete:
use Illuminate\Support\Facades\Blade;use VendorPackage\View\Components\AlertComponent; /** * Bootstrap your package's services. */public function boot(): void{ Blade::component('package-alert', AlertComponent::class);}
Una vez que tu componente haya sido registrado, puede ser renderizado utilizando su alias de etiqueta:
<x-package-alert/>
Autocarga de Componentes de Paquete
Alternativamente, puedes usar el método componentNamespace
para autoload de clases de componentes por convención. Por ejemplo, un paquete Nightshade
podría tener componentes Calendar
y ColorPicker
que residen dentro del espacio de nombres Nightshade\Views\Components
:
use Illuminate\Support\Facades\Blade; /** * Bootstrap your package's services. */public function boot(): void{ Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');}
Esto permitirá el uso de componentes de paquetes por su espacio de nombres de proveedor utilizando la sintaxis package-name::
:
<x-nightshade::calendar /><x-nightshade::color-picker />
Blade detectará automáticamente la clase que está vinculada a este componente utilizando la notación PascalCase en el nombre del componente. También se admiten subdirectorios utilizando la notación "punto".
Componentes Anónimos
Si tu paquete contiene componentes anónimos, deben colocarse dentro de un directorio components
del directorio "views" de tu paquete (como se especifica en el método loadViewsFrom
). Luego, puedes renderizarlos prefijando el nombre del componente con el espacio de nombres de la vista del paquete:
<x-courier::alert />
Comando Artisan "About"
El comando Artisan about
incorporado de Laravel proporciona un resumen del entorno y la configuración de la aplicación. Los paquetes pueden añadir información adicional a la salida de este comando a través de la clase AboutCommand
. Típicamente, esta información se puede agregar desde el método boot
del proveedor de servicios de tu paquete:
use Illuminate\Foundation\Console\AboutCommand; /** * Bootstrap any application services. */public function boot(): void{ AboutCommand::add('My Package', fn () => ['Version' => '1.0.0']);}
Comandos
Para registrar los comandos Artisan de tu paquete con Laravel, puedes usar el método commands
. Este método espera un array de nombres de clases de comando. Una vez que los comandos hayan sido registrados, puedes ejecutarlos utilizando la Artisan CLI:
use Courier\Console\Commands\InstallCommand;use Courier\Console\Commands\NetworkCommand; /** * Bootstrap any package services. */public function boot(): void{ if ($this->app->runningInConsole()) { $this->commands([ InstallCommand::class, NetworkCommand::class, ]); }}
Activos Públicos
Tu paquete puede tener activos como JavaScript, CSS e imágenes. Para publicar estos activos en el directorio public
de la aplicación, utiliza el método publishes
del proveedor de servicios. En este ejemplo, también añadiremos una etiqueta de grupo de activos public
, que se puede usar para publicar fácilmente grupos de activos relacionados:
/** * Bootstrap any package services. */public function boot(): void{ $this->publishes([ __DIR__.'/../public' => public_path('vendor/courier'), ], 'public');}
Ahora, cuando los usuarios de tu paquete ejecuten el comando vendor:publish
, tus activos se copiarán a la ubicación de publicación especificada. Dado que los usuarios normalmente necesitarán sobrescribir los activos cada vez que se actualice el paquete, puedes usar el flag --force
:
php artisan vendor:publish --tag=public --force
Publicación de Grupos de Archivos
Es posible que desees publicar grupos de activos y recursos del paquete de forma separada. Por ejemplo, es posible que desees permitir que tus usuarios publiquen los archivos de configuración de tu paquete sin verse obligados a publicar los activos de tu paquete. Puedes hacer esto "etiquetándolos" al llamar al método publishes
desde un proveedor de servicios del paquete. Por ejemplo, usemos etiquetas para definir dos grupos de publicación para el paquete courier
(courier-config
y courier-migrations
) en el método boot
del proveedor de servicios del paquete:
/** * Bootstrap any package services. */public function boot(): void{ $this->publishes([ __DIR__.'/../config/package.php' => config_path('package.php') ], 'courier-config'); $this->publishesMigrations([ __DIR__.'/../database/migrations/' => database_path('migrations') ], 'courier-migrations');}
Ahora tus usuarios pueden publicar estos grupos por separado haciendo referencia a su etiqueta al ejecutar el comando vendor:publish
:
php artisan vendor:publish --tag=courier-config