[Из песочницы] Делим Laravel на компоненты

?v=1

Привет, Хабр. Недавно получил в руки интересный проект, который, несмотря на свою простоту требовал не использовать какой-либо фреймворк. О пакетах речи не шло, поэтому было принято решение использовать привычные компоненты 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

© Habrahabr.ru