Developing your packages in Laravel 5

Published 2 years ago by davidxd33

I spent all day trying to get my packages flow going and after intense research and tests, I came up with a nice flexible way to develop packages without illuminate/workbench.

Setup your home for making packages (your workbench).


I created a directory called "packages" in my application root. Inside of the packages directory, follow the basic structure of any package (Vendor/Package/src).

It should look like so:

packages /
    Vendor /
        Package /
            src/

Setup your composer.json


Navigate to your package directory (Vendor/Package) and run:

composer init

It will ask a series of questions to generate your composer.json. You may include any required dependencies as you wish, we'll talk about autoloading them later.

Create your PackageServiceProvider


Like any old package, create your PackageServiceProvider inside of the src folder of your package. For more information on that, refer to the docs.

Autoload your package with PSR-4


Back to your project root, edit your composer.json to autoload your package namespace.

This is what your autoload section of composer.json should look like:

"autoload": {
    "psr-4": {
        "App\\": "app/",
        "Vendor\\Package\\": "packages/Vendor/Package/src"
    }
},

Create an application PackageServiceProvider


Here's the part that was tricky for me. When I wanted to use a third party in my package, I was getting a class not found exception. It was strange because I've already done my composer update. It's when I noticed that illuminate/workbench actually was requiring the composer autoload.php for all your packages. Now we're responsible for this.

Use a service provider to autoload all packages for you. Run:

php artisan make:provider PackageServiceProvider

Here's my provider (snipped for space): http://laravel.io/bin/RE24X

If you would like to skip making the PackageServiceProvider, you can manually require to autoload.php file from your package's boot() method.

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    require __DIR__ . '/../vendor/autoload.php';
}

Add your providers into your app config


Finally like all providers, add them to your config/app.php.

'providers' =>  [
    /*
    * Application Service Providers
    */
    'App\Providers\AppServiceProvider',
    'App\Providers\BusServiceProvider',
    'App\Providers\ConfigServiceProvider',
    'App\Providers\EventServiceProvider',
    'App\Providers\RouteServiceProvider',
    'App\Providers\RepositoryServiceProvider',

    'App\Providers\PackageServiceProvider',

    /*
    * Package Service Providers
    */
    'Vendor\Package\PackageServiceProvider',
]

That should be it. You now can develop your packages freely in laravel 5. If you encounter any errors or have a better solution, please tell me as I found this to be an easy way to develop packages in laravel 5.

Sources:

aedart
aedart
2 years ago (21,035 XP)

Not bad tip - ty

Moe
Moe
2 years ago (17,070 XP)

I realy appreciate your explanation.

@TaylorOtwell it should be nice to have some lessons about the package development.

bbloom

I put my packages in a root folder called "packages", to avoid potential problems putting it in "vendor". Otherwise, similar set-up to what I'm doing.

davidxd33

@bbloom This method does put packages in a folder called "packages" in root. The vendor folder is for published packages.

Jeroen

Great! I was looking for this, thank you. You should make this a package. :D

stefr
stefr
2 years ago (19,565 XP)

Excellent post!

stefr
stefr
2 years ago (19,565 XP)

@davidxd33 Maybe a newbie question: I made a package using this post. It works very well! However, if I would like to include this package in another project using composer it wil be installed in the /vendor/ directory. Now I'm confused. we've hardcoded some links to the /packages/ dir in the code for example:

    public function boot()
    {
            $this->loadAutoloader(base_path('packages'));
    }

and

"autoload": {
    "psr-4": {
        "App\\": "app/",
        "Vendor\\Package\\": "packages/Vendor/Package/src"
    }
},

So, is this package not intended to be reused?

dberry
dberry
2 years ago (38,175 XP)
stefr
stefr
2 years ago (19,565 XP)

@dberry Thanks for the reply. Can you tell me why it is bad to develop in the vendor directory? To me it looks like the easiest way right now.

dberry
dberry
2 years ago (38,175 XP)

The vendor directory should be packages that are managed by composer, it's not a development directory.

I mean technically you could, but it's frowned upon. Using something like Studio, it's extremely simple to do what you're wanting to do, it takes care of all of the auto-loading for you kind of like the old workbench feature in Laravel 4.2 did, with the exception of it's cleaner (as it's a composer plugin) and it's not Laravel specific (meaning it doesn't do the service provider, etc...)

stefr
stefr
2 years ago (19,565 XP)

OK, thanks @dberry

Jeroen

I created a cli tool that creates a package for you very easily: https://github.com/Jeroen-G/laravel-packager I just finished it, I'd love to get feedback on it.

tomicakorac

Guys, is there a way to register a package's service provider from within that package? I.e. can I register a service provider without adding it to the 'providers' array in 'config/app.php'?

MarkRedeman

@tomicakorac you can use $this->app->register('Acme\ServiceProvider'); to register a different service provider from your own service provider.

Sign In or create a forum account to participate in this discussion.