[Из песочницы] Делим Laravel на компоненты
Привет, Хабр. Недавно получил в руки интересный проект, который, несмотря на свою простоту требовал не использовать какой-либо фреймворк. О пакетах речи не шло, поэтому было принято решение использовать привычные компоненты Laravel. Если есть необходимость в использовании очередей, Eloquent или контейнера — добро пожаловать под кат.
О простоте деления фреймворка на компоненты
Начиная с Laravel 4, все компоненты — отдельные пакеты, которые в теории можно заставить работать в любом PHP проекте. Однако, некоторые компоненты требуют дополнительной настройки, которая в основном фреймворке спрятана под капот.
Компоненты
Контейнер
Из всех рассматриваемых компонентов illuminate/container
— самый простой в установке и использовании.
make(Foo::class);
Впрочем, вызов статичного метода на классе Container
при каждом использовании контейнера — не самая лучшая идея. В фреймворке доступен хелпер app()
, который вернёт нам инстанс глобального контейнера, однако, нам такой нужно создать вручную.
Создадим файл helpers.php
для таких хелперов, и добавим его в автозагрузку.
"autoload": {
"files": [
"src/helpers.php"
],
"psr-4": {
"YourApp\\": "src/"
}
}
Добавляем хелпер app()
в файл.
make($abstract, $parameters);
}
}
Готово. Можно пробовать использовать хелпер.
Query Builder и Eloquent
Для использования компонента illuminate/database
мы будем использовать Capsule\Manager
— класс, предназначенный для работы с построителем запросов вне Laravel.
Начнём с настройки подключения к БД. Желательно эту настройку проводить на этапе запуска вашего приложения, сразу после подключения autoload.php
.
addConnection([
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database',
'username' => 'root',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
]);
// Позволяет использовать статичные вызовы при работе с Capsule.
$manager->setAsGlobal();
Можно начинать работу с построителем запросов.
get();
Что насчёт Eloquent?
С миграциями ситуация сложнее — с одной стороны, в комплекте есть Schema Builder. С другой — автоматический механизм запуска миграций отсутствует.
create('orders', function ($table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
Для запуска достаточно выполнить файл с миграцией: php migration.php
Очереди
У очередей тоже есть свой Capsule
, однако аналоги queue:work
и queue:listen
необходимо писать вручную.
Начнём с класса Application
. В Laravel этот класс используется как глобальный инстанс контейнера, который помимо методов Illuminate\Container\Container
содержит вспомогательные методы для работы с фреймворком (текущая версия, пути к хранилищу, ресурсам). Однако, наш класс будет содержать лишь один метод — isDownForMaintenance
. Он необходим для работы воркера, так как определяет состояние работы приложения в данный момент.
Далее, нам необходимо зарегистрировать провайдер illuminate/events
, и забиндить контракт Illuminate\Contracts\Events\Dispatcher
к алиасу events
.
bind(Dispatcher::class, 'events');
Теперь необходимо создать инстанс Capsule
, и добавить туда конфигурации соединений.
Пример конфигурации для БД
addConnection([
'driver' => 'database',
'table' => 'jobs',
'connection' => 'default',
'queue' => 'default',
], 'default');
// Также, как и с Illuminate\Database\Capsule\Manager позволяет использовать статичные вызовы для очередей
$queue->setAsGlobal();
$connection = Capsule::schema()->getConnection();
$resolver = new ConnectionResolver(['default' => $connection]);
$queue->getQueueManager()->addConnector('database', function () use ($resolver) {
return new DatabaseConnector($resolver);
});
Пример конфигурации для Redis (требует установленного illuminate/redis
)
bind('redis', function () use ($container) {
return new RedisManager($container, 'predis', [
'default' => [
'host' => '127.0.0.1',
'password' => null,
'port' => 6379,
'database' => 0,
]
]);
});
$queue = new Manager($container);
$queue->addConnection([
'driver' => 'redis',
'connection' => 'default',
'queue' => 'default',
], 'default');
$queue->setAsGlobal();
Последний этап в конфигурации — добавление аналога Exception Handler.
bind('exception.handler', function () {
return new Handler;
});
Конфигурация очередей завершена. Теперь можно приступать к написанию queue:work
.
daemon('default', 'default', new WorkerOptions);
Теперь для запуска воркера очередей достаточно написать php worker.php
.
Если же есть необходимость в использовании queue:listen
, то нужно создавать два отдельных файла. Один — демон, который слушает очередь, и запускает второй файл на каждый новый job. Второй файл, в свою очередь, выступает в роли исполнителя задачи.
worker.php
__DIR__]);
$worker->setOutputHandler(function ($type, $line) {
echo $line;
});
$worker->listen('default', 'default', new ListenerOptions);
work.php
runNextJob('default', 'default', new WorkerOptions);
Переходим к использованию. Все методы можно просмотреть в API