Creating A Laravel Preset Package

Published September 22nd, 2018
9 minute read
Warning!
This was written over two years ago, so some information might be outdated. Frameworks and best practices change. The web moves fast! You may need to adjust a few things if you follow this article word for word.

Laravel provides frontend scaffolding, but you may want a more customized boilerplate to start projects from. Learn to create your own package to do just that!

This article is broken up into two parts:

We'll be creating and working on a Composer package and then using that package to build a reusable Laravel preset customized how we want.

Create a new laravel project to develop and test our preset on:

1composer create-project --prefer-dist laravel/laravel
1composer create-project --prefer-dist laravel/laravel

Now we'll have a laravel folder with the default framework installed. Next, create a subfolder for our composer package to live in. Then we can use composer init to generate a composer.json file.

1cd laravel && mkdir my-preset
2cd my-preset && composer init
1cd laravel && mkdir my-preset
2cd my-preset && composer init

You can go with the default options when you run composer init. We'll be changing the my-preset/composer.json file by hand in a moment anyway. Composer has a page that outlines all the options if you want to know more about them.

Once you've generated your composer.json file, open it in the text editor of your choice and add "laravel/framework": "^5.7" to therequire: {} object.

Heads Up!
Make sure you're editing the my-preset/composer.json file, not the one in the laravel folder.

Here's an example of what the composer.json file might look like at this point:

1{
2 "name": "austenc/my-preset",
3 "require": {
4 "laravel/framework": "^5.7"
5 }
6}
1{
2 "name": "austenc/my-preset",
3 "require": {
4 "laravel/framework": "^5.7"
5 }
6}

Now for the tricky part! We've established the composer file for our package, but we still need to tell composer (and our main Laravel app) where to find it. To accomplish this, we'll use composer's path option. Then the my-preset folder will be automatically symlinked to the vendor folder. This way we can develop the package in the context of a "real" app.

Open up the laravel/composer.json file and add our package to the require-dev section.

1"require-dev": {
2 // other dev requirements will be here
3 "austenc/my-preset": "*"
4},
1"require-dev": {
2 // other dev requirements will be here
3 "austenc/my-preset": "*"
4},

Then add a repositories section that looks like this:

1"repositories": [
2 {
3 "type": "path",
4 "url": "./my-preset"
5 },
6],
1"repositories": [
2 {
3 "type": "path",
4 "url": "./my-preset"
5 },
6],

Try running composer update from the laravel folder. You should see something like this:

1Installing austenc/my-preset (dev-master): Symlinking from ./my-preset
1Installing austenc/my-preset (dev-master): Symlinking from ./my-preset

Checkpoint Reached!
Make sure you don't get errors when running composer update. If you do, retrace your steps and fix any errors before moving on. Now that the link is set up, wewon't have to run composer update after making changes to our package code! 👍

This is a great point to run git init in our my-preset directory. After all, we don't want to version our package files in our main app, they should be separate! Having a git repository inside another one automatically makes the (outer) repo ignore the inner one's files, so we can use that to our advantage here.

Our package doesn't actually contain any code yet, so let's change that! Packages usually contain a src folder which has all the namespaced PHP files.

All of the following steps will be assuming the my-preset folder is our main directory.

First, We need to create a Preset class now that does the work of our preset. Create a src/Preset.php file in the package folder like so:

1<?php
2namespace AustenCam\Preset;
3 
4use Illuminate\Foundation\Console\Presets\Preset as BasePreset;
5class Preset extends BasePreset
6{
7 public static function install()
8 {
9 // do work (see part two!)
10 }
11}
1<?php
2namespace AustenCam\Preset;
3 
4use Illuminate\Foundation\Console\Presets\Preset as BasePreset;
5class Preset extends BasePreset
6{
7 public static function install()
8 {
9 // do work (see part two!)
10 }
11}

Next, we'll need to register our "do work" code via a Service Provider. Create a new PresetServiceProvider.php file in the src/ directory with the following code:

1<?php
2namespace AustenCam\Preset;
3 
4use Illuminate\Support\ServiceProvider;
5use Illuminate\Foundation\Console\PresetCommand;
6 
7class PresetServiceProvider extends ServiceProvider
8{
9 public function boot()
10 {
11 PresetCommand::macro('austencam', function ($command) {
12 // Do the preset work
13 Preset::install();
14 
15 // Let the user know what we've done
16 $command->info('Your preset has been installed successfully.');
17 });
18 }
19}
1<?php
2namespace AustenCam\Preset;
3 
4use Illuminate\Support\ServiceProvider;
5use Illuminate\Foundation\Console\PresetCommand;
6 
7class PresetServiceProvider extends ServiceProvider
8{
9 public function boot()
10 {
11 PresetCommand::macro('austencam', function ($command) {
12 // Do the preset work
13 Preset::install();
14 
15 // Let the user know what we've done
16 $command->info('Your preset has been installed successfully.');
17 });
18 }
19}

Let's break this down. When we boot up our service provider, we are adding a Macro to the framework's base PresetCommand class called austencam. This is Laravel's way of allowing us to easily extend core framework features. Basically it says, "Add austencam as an available option to the php artisan preset command".

Diving In
If you're curious how this works, the Macroable trait is what makes it possible. It can also be used for many other things such as HTTP responses, Collections, etc...

See those namespace AustenCam\Preset lines? Right now the above code won't do anything because we need to tell composer where that namespace lives! Add these sections to your package's composer.json file:

1"autoload": {
2 "psr-4": {
3 "AustenCam\\Preset\\": "src/"
4 }
5},
6"extra": {
7 "laravel": {
8 "providers": [
9 "AustenCam\\Preset\\PresetServiceProvider"
10 ]
11 }
12}
1"autoload": {
2 "psr-4": {
3 "AustenCam\\Preset\\": "src/"
4 }
5},
6"extra": {
7 "laravel": {
8 "providers": [
9 "AustenCam\\Preset\\PresetServiceProvider"
10 ]
11 }
12}

When our package is installed, composer reads the autoload section of its composer.json file so it knows how to automatically load any classes from that namespace when referenced. Since version 5.5, Laravel can automatically discover package service providers, which is what the extra section configures. This just makes it easier to use the package, since we don't have to register anything manually in config/app.php when we use it. Pretty cool!

Now that we've updated our package's composer.json, we need to run composer update one last time from the main laravel app, not our package directory. If everything was correct you should see Discovered Package: austenc/my-preset near the end of the output.

Now we should be able to run php artisan preset austencam and see it output our preset message. 🙏

1Your preset has been installed successfully.
1Your preset has been installed successfully.

Congrats! You've set up a composer package development environment from scratch. In part two we'll configure our preset to set things up just the way we like!

Part Two - Configuring the Laravel Preset

If you have any questions feel free to reach out on Twitter or elsewhere, I would be happy to help you out! 👍

I should also mention there are many other presets available from the community. Check these out for other ideas to add to your own preset.

Enjoy this article? Follow me on Twitter for more tips, articles and links.
😢 Awww, nobody has liked or mentioned this on Twitter yet.

Want Updates?

Sign up here if you want to stay in the loop about new articles or products I'm making.
I'll never spam you. Unsubscribe at any time.
Copyright ©2024 Austen Cameron