Laravel 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 Behat.

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 requesting them in your composer.json 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.

A Note On Facades
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, your package will not typically have access to all of Laravel’s testing helpers. If you would like to be able to write your package tests as if they existed inside a typical Laravel application, you may use the Orchestral Testbench package.

Package Discovery
In a Laravel application’s config/app.php configuration file, the providers option defines a list of service providers that should be loaded by Laravel. When someone installs your package, you will typically want your service provider to be included in this list. Instead of requiring users to manually add your service provider to the list, you may define the provider in the extra section of your package’s composer.json file. In addition to service providers, you may also list any facades you would like to be registered:

"extra": {
    "laravel": {
        "providers": [
            "Barryvdh\\Debugbar\\ServiceProvider"
        ],
        "aliases": {
            "Debugbar": "Barryvdh\\Debugbar\\Facade"
        }
    }
},

Service Providers
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 their documentation.

Configuration
Typically, you will need to publish your package’s configuration file to the application’s own config directory. This will allow users of your package to easily override your default configuration options. To allow your configuration files to be published, call the publishes method from the boot method of your service provider:

public function boot()
{
    $this->publishes([
        __DIR__.'/path/to/config/courier.php' => config_path('courier.php'),
    ]);
}

Migrations
If your package contains database migrations, 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:

public function boot()
{
    $this->loadMigrationsFrom(__DIR__.'/path/to/migrations');
}

public function boot()
{
    $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier');
}

Commands
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 Artisan CLI:

public function boot()
{
    if ($this->app->runningInConsole()) {
        $this->commands([
            FooCommand::class,
            BarCommand::class,
        ]);
    }
}

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:

public function boot()
{
    $this->publishes([
        __DIR__.'/path/to/assets' => public_path('vendor/courier'),
    ], 'public');
}

Publishing File Groups
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:

public function boot()
{
    $this->publishes([
        __DIR__.'/../config/package.php' => config_path('package.php')
    ], 'config');

    $this->publishes([
        __DIR__.'/../database/migrations/' => database_path('migrations')
    ], 'migrations');
}