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-preset2cd my-preset && composer init
1cd laravel && mkdir my-preset2cd my-preset && composer init
You can go with the default options when you run
composer init
. We'll be changing themy-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 themy-preset/composer.json
file, not the one in thelaravel
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 here3 "austenc/my-preset": "*"4},
1"require-dev": {2 // other dev requirements will be here3 "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 runcomposer 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<?php2namespace AustenCam\Preset;34use Illuminate\Foundation\Console\Presets\Preset as BasePreset;5class Preset extends BasePreset6{7 public static function install()8 {9 // do work (see part two!)10 }11}
1<?php2namespace AustenCam\Preset;34use Illuminate\Foundation\Console\Presets\Preset as BasePreset;5class Preset extends BasePreset6{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<?php2namespace AustenCam\Preset;34use Illuminate\Support\ServiceProvider;5use Illuminate\Foundation\Console\PresetCommand;67class PresetServiceProvider extends ServiceProvider8{9 public function boot()10 {11 PresetCommand::macro('austencam', function ($command) {12 // Do the preset work13 Preset::install();1415 // Let the user know what we've done16 $command->info('Your preset has been installed successfully.');17 });18 }19}
1<?php2namespace AustenCam\Preset;34use Illuminate\Support\ServiceProvider;5use Illuminate\Foundation\Console\PresetCommand;67class PresetServiceProvider extends ServiceProvider8{9 public function boot()10 {11 PresetCommand::macro('austencam', function ($command) {12 // Do the preset work13 Preset::install();1415 // Let the user know what we've done16 $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.