In Laravel, one of the big questions is how best install packages. Traditionally, we would create a nasty bit of readme that included a script that looks like this:
php artisan config:publish rtablada/laravel-faq
While this isn't that tough, it can be a bit confusing and is a bit long. I much prefer to run something like this:
php artisan faq:config
It is shorter, sweeter and gives that extra comfort.
So, to start we will create a console namespace for our commands to go into.
In src/Rtablada/LaravelFaq/Console/ConfigureCommand.php
start with a command skeleton:
<?php namespace Rtablada\LaravelFaq\Console;
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class ConfigureCommand extends Command {
/**
* The console command name.
*
* @var string
*/
protected $name = 'command:name';
/**
* The console command description.
*
* @var string
*/
protected $description = '';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function fire()
{
//
}
}
Then we will create a simple command by filling things in and using the call
method which can be used to call any artisan command.
class ConfigureCommand extends Command {
protected $name = 'faq:config';
protected $description = 'Publishes configuration for Laravel FAQ.';
public function fire()
{
$this->call('config:publish', array('package' => 'rtablada/laravel-faq'));
}
}
Now, on to trickier fish.
Yesterday, we made the database interactions for our models flexible.
While, this is very cool, it makes things a bit awkward when running migrations.
We could create funny looking migrations which change the default connection but this gets a bit messy and process intensive.
Luckily, the artisan migrate
command has a --database
flag that designates what connection to use.
So the migration command for our package would be
php artisan migrate --package="rtablada/laravel-faq" --database="faq"
Still completely readable, but let's make it php artisan faq:migrate
class MigrateCommand extends Command {
protected $name = 'faq:migrate';
protected $description = 'Migrates the database for Laravel FAQ.';
public function fire()
{
$this->call('migrate', array('--package' => 'rtablada/laravel-faq', '--database' => 'faq'));
}
}
The last minor command I want to add is php artisan asset:publish rtablada/laravel-faq
class AssetsCommand extends Command {
protected $name = 'faq:assets';
protected $description = 'Publishes assets for Laravel FAQ.';
public function fire()
{
$this->call('asset:publish', array('package' => 'rtablada/laravel-faq'));
}
}
Finally, lets wrap this into a single install command
class InstallCommand extends Command {
protected $name = 'faq:assets';
protected $description = 'Publishes assets for Laravel FAQ.';
public function fire()
{
$this->call('faq:config');
$this->call('faq:assets');
if ($this->confirm('Have you configured your database yet?')) {
$this->call('faq:config');
} else {
$this->comment('Your database has not been migrated, run artisan faq:migrate before use');
}
}
}
One added feature is the confirm
in the installer.
This will pause running the migration command while a user is configuring the database.
If the user responds no, then it will tell them to migrate manually before use.
Now that we have our commands, we have to register them in our src/rtablada/LaravelFaq/LaravelFaqServiceProvider
public function register()
{
$this->registerCommands();
}
public function registerCommands()
{
$this->registerMigrateCommand();
$this->registerConfigureCommand();
$this->registerAssetsCommand();
$this->registerInstallCommand();
$this->commands(
'laravel-faq::commands.migrate',
'laravel-faq::commands.config',
'laravel-faq::commands.assets',
'laravel-faq::commands.install'
);
}
public function registerMigrateCommand()
{
$this->app['laravel-faq::commands.migrate'] = $this->app->share(function($app)
{
return new Console\MigrateCommand;
});
}
public function registerConfigureCommand()
{
$this->app['laravel-faq::commands.config'] = $this->app->share(function($app)
{
return new Console\ConfigureCommand;
});
}
public function registerAssetsCommand()
{
$this->app['laravel-faq::commands.assets'] = $this->app->share(function($app)
{
return new Console\AssetsCommand;
});
}
public function registerInstallCommand()
{
$this->app['laravel-faq::commands.install'] = $this->app->share(function($app)
{
return new Console\InstallCommand;
});
}
Now we have created an easier, more flexible, less error prone installation process than before in just a few minutes.