Один из основных вопросов в Laravel — как лучше устанавливать пакеты. Традиционно мы имеем неприятную часть файла readme, которая содержит подобную инструкцию:
shphp artisan config:publish rtablada/laravel-faq
Это не очень сложно, но может быть немного запутанным и длинным. Гораздо приятнее было бы иметь команду наподобие:
shphp artisan faq:config
Итак, для начала мы создадим для наших команд пространство имен в консоли. Начнем с написания кода-заглушки в src/Rtablada/LaravelFaq/Console/ConfigureCommand.php:
<?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 {
/**
* Имя консольной команды.
*
* @var string
*/
protected $name = 'command:name';
/**
* Описание консольной команды.
*
* @var string
*/
protected $description = '';
/**
* Создание нового экземпляра команды.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Выполнение консольной команды.
*
* @return void
*/
public function fire()
{
//
}
}
Затем мы создадим простую команду, постеменно заполняя класс кодом и используя метод call, с помощью которого можно вызывать любые команды Artisan.
class ConfigureCommand extends Command {
protected $name = 'faq:config';
protected $description = 'Публикует параметры настройки Laravel FAQ.';
public function fire()
{
$this->call('config:publish', array('package' => 'rtablada/laravel-faq'));
}
}
Теперь перейдем к хитростям. Вчера мы сделали взаимодействие наших моделей с БД более гибким. Это очень здорово, но становится немного неудобно выполнять миграции. Мы могли бы создать забавные миграции, которые меняют подключение по умолчанию, но это было бы немного неряшливо и ресурсоёмко. К счастью, у команды artisan migrate есть флаг --database, который указывает какое подключение надо использовать. Поэтому команда миграции для нашего пакета будет такой:
shphp artisan migrate --package="rtablada/laravel-faq" --database="faq"
Команда по-прежнему вполне читаема, но давайте сделаем её shphp artisan faq:migrate
class MigrateCommand extends Command {
protected $name = 'faq:migrate';
protected $description = 'Выполняет миграции для Laravel FAQ.';
public function fire()
{
$this->call('migrate', array('--package' => 'rtablada/laravel-faq', '--database' => 'faq'));
}
}
Последняя незначительная команда, которую я хочу добавить — это shphp artisan asset:publish rtablada/laravel-faq
:
class AssetsCommand extends Command {
protected $name = 'faq:assets';
protected $description = 'Публикует внешние ресурсы Laravel FAQ.';
public function fire()
{
$this->call('asset:publish', array('package' => 'rtablada/laravel-faq'));
}
}
Наконец, давайте соберем все это в одну команду установки:
class InstallCommand extends Command {
protected $name = 'faq:assets';
protected $description = 'Публикует внешние ресурсы Laravel FAQ.';
public function fire()
{
$this->call('faq:config');
$this->call('faq:assets');
if ($this->confirm('Вы уже настроили БД?')) {
$this->call('faq:config');
} else {
$this->comment('БД ещё не была мигрирована, перед использованием выполните artisan faq:migrate');
}
}
}
В установщик добавлена функция подтверждения confirm. Она будет приостанавливать выполнение команды миграции, пока пользователь настраивает БД. Если пользователь ответит «нет», тогда она сообщит ему о необходимости провести миграцию вручную перед использованием.
Теперь, когда у нас есть команды, нам надо зарегистрировать их в нашем 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;
});
}
Таким образом, за несколько минут мы сделали процесс установки более простым, более гибким и менее предрасположенным к ошибкам.