Package Development

    Packages are the primary way of adding functionality to Laravel. Packages might be anything from a great way to work with dates like Carbon, or an entire BDD testing framework like .

    Of course, there are different types of packages. Some packages are stand-alone, meaning they work with any PHP framework. Carbon and Behat are examples of stand-alone packages. Any of these packages may be used with Laravel by simply requesting them in your file.

    On the other hand, other packages are specifically intended for use with Laravel. These packages may have routes, controllers, views, and configuration specifically intended to enhance a Laravel application. This guide primarily covers the development of those packages that are Laravel specific.

    When writing a Laravel application, it generally does not matter if you use contracts or facades since both provide essentially equal levels of testability. However, when writing packages, it is best to use instead of facades. Since your package will not have access to all of Laravel's testing helpers, it will be easier to mock or stub a contract than to mock a facade.

    Service Providers

    are the connection points between your package and Laravel. A service provider is responsible for binding things into Laravel's service container and informing Laravel where to load package resources such as views, configuration, and localization files.

    A service provider extends the Illuminate\Support\ServiceProvider class and contains two methods: register and boot. The base ServiceProvider class is located in the illuminate/support Composer package, which you should add to your own package's dependencies. To learn more about the structure and purpose of service providers, check out .

    To define routes for your package, pass the routes file path to the loadRoutesFrom method from within your package service provider's boot method. From within your routes file, you may use the Illuminate\Support\Facades\Route facade to just as you would within a typical Laravel application:

    Resources

    1. /**
    2. * Perform post-registration booting of services.
    3. *
    4. * @return void
    5. */
    6. public function boot()
    7. {
    8. $this->publishes([
    9. __DIR__.'/path/to/config/courier.php' => config_path('courier.php'),
    10. ]);
    11. }

    Now, when users of your package execute Laravel's vendor:publish command, your file will be copied to the specified publish location. Of course, once your configuration has been published, its values may be accessed like any other configuration file:

    1. $value = config('courier.option');

    Default Package Configuration

    You may also merge your own package configuration file with the application's published copy. This will allow your users to define only the options they actually want to override in the published copy of the configuration. To merge the configurations, use the mergeConfigFrom method within your service provider's register method:

    1. /**
    2. *
    3. * @return void
    4. */
    5. public function register()
    6. {
    7. $this->mergeConfigFrom(
    8. __DIR__.'/path/to/config/courier.php', 'courier'
    9. );
    10. }

    {note} This method only merges the first level of the configuration array. If your users partially define a multi-dimensional configuration array, the missing options will not be merged.

    If your package contains , you may use the loadMigrationsFrom method to inform Laravel how to load them. The loadMigrationsFrom method accepts the path to your package's migrations as its only argument:

    1. /**
    2. * Perform post-registration booting of services.
    3. *
    4. * @return void
    5. */
    6. public function boot()
    7. {
    8. $this->loadMigrationsFrom(__DIR__.'/path/to/migrations');
    9. }

    Once your package's migrations have been registered, they will automatically be run when the php artisan migrate command is executed. You do not need to export them to the application's main database/migrations directory.

    If your package contains , you may use the method to inform Laravel how to load them. For example, if your package is named courier, you should add the following to your service provider's boot method:

    Package translations are referenced using the package::file.line syntax convention. So, you may load the courier package's welcome line from the messages file like so:

    1. echo trans('courier::messages.welcome');

    Publishing Translations

    If you would like to publish your package's translations to the application's resources/lang/vendor directory, you may use the service provider's publishes method. The publishes method accepts an array of package paths and their desired publish locations. For example, to publish the translation files for the courier package, you may do the following:

    1. /**
    2. * Perform post-registration booting of services.
    3. *
    4. * @return void
    5. */
    6. public function boot()
    7. {
    8. $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier');
    9. $this->publishes([
    10. __DIR__.'/path/to/translations' => resource_path('lang/vendor/courier'),
    11. ]);
    12. }

    Now, when users of your package execute Laravel's vendor:publish Artisan command, your package's translations will be published to the specified publish location.

    To register your package's with Laravel, you need to tell Laravel where the views are located. You may do this using the service provider's loadViewsFrom method. The loadViewsFrom method accepts two arguments: the path to your view templates and your package's name. For example, if your package's name is courier, you would add the following to your service provider's boot method:

    1. /**
    2. * Perform post-registration booting of services.
    3. *
    4. * @return void
    5. */
    6. public function boot()
    7. {
    8. $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
    9. }

    Package views are referenced using the package::view syntax convention. So, once your view path is registered in a service provider, you may load the admin view from the courier package like so:

    1. return view('courier::admin');
    2. });

    Overriding Package Views

    When you use the loadViewsFrom method, Laravel actually registers two locations for your views: the application's resources/views/vendor directory and the directory you specify. So, using the courier example, Laravel will first check if a custom version of the view has been provided by the developer in resources/views/vendor/courier. Then, if the view has not been customized, Laravel will search the package view directory you specified in your call to loadViewsFrom. This makes it easy for package users to customize / override your package's views.

    Publishing Views

    If you would like to make your views available for publishing to the application's resources/views/vendor directory, you may use the service provider's publishes method. The method accepts an array of package view paths and their desired publish locations:

    Now, when users of your package execute Laravel's vendor:publish Artisan command, your package's views will be copied to the specified publish location.

    To register your package's Artisan commands with Laravel, you may use the commands method. This method expects an array of command class names. Once the commands have been registered, you may execute them using the :

    1. /**
    2. * Bootstrap the application services.
    3. *
    4. * @return void
    5. */
    6. public function boot()
    7. {
    8. if ($this->app->runningInConsole()) {
    9. $this->commands([
    10. FooCommand::class,
    11. BarCommand::class,
    12. ]);
    13. }
    14. }

    Public Assets

    Your package may have assets such as JavaScript, CSS, and images. To publish these assets to the application's public directory, use the service provider's publishes method. In this example, we will also add a public asset group tag, which may be used to publish groups of related assets:

    1. /**
    2. * Perform post-registration booting of services.
    3. *
    4. * @return void
    5. */
    6. public function boot()
    7. {
    8. $this->publishes([
    9. __DIR__.'/path/to/assets' => public_path('vendor/courier'),
    10. ], 'public');
    11. }

    Now, when your package's users execute the vendor:publish command, your assets will be copied to the specified publish location. Since you will typically need to overwrite the assets every time the package is updated, you may use the —force flag:

    1. php artisan vendor:publish --tag=public --force

    You may want to publish groups of package assets and resources separately. For instance, you might want to allow your users to publish your package's configuration files without being forced to publish your package's assets. You may do this by "tagging" them when calling the publishes method from a package's service provider. For example, let's use tags to define two publish groups in the boot method of a package service provider:

    1. /**
    2. * Perform post-registration booting of services.
    3. *
    4. * @return void
    5. */
    6. public function boot()
    7. {
    8. $this->publishes([
    9. __DIR__.'/../config/package.php' => config_path('package.php')
    10. ], 'config');
    11. $this->publishes([
    12. __DIR__.'/../database/migrations/' => database_path('migrations')
    13. }