Laravel Pipelines: Оптимизация Разработки сложных web-приложений

Laravel Pipelines: Оптимизация Разработки сложных web-приложений

Laravel Pipelines – это малоизвестная, но мощная возможность Laravel, которая не описана в официальной документации. Тем не менее, этот инструмент широко используется внутри фреймворка для выполнения последовательных операций. В этой статье мы рассмотрим, как Laravel Pipelines может быть полезен в разработке CRM-систем, а также приведем примеры использования и полезные ссылки.

В каких задачах Laravel Pipelines даст выгоды

Представим, что у нас есть некоторые исходные данные, с которыми нужно произвести последовательно ряд действий. Например, добавление нового контакта в CRM-систему.

Пример 1: Добавление нового контакта

Когда пользователь добавляет новый контакт, данные приходят в контроллер. Контакт проходит через ряд шагов перед добавлением в базу данных:

  1. Проверка наличия всех обязательных полей.
  2. Валидация данных: проверка корректности email, телефона и т.д.
  3. Удаление лишних пробелов и форматирование текста.
  4. Проверка уникальности контакта.
  5. Создание уникального идентификатора контакта.
  6. Сохранение контакта в базу данных.

Пример 2: Обработка запроса на поддержку

Когда пользователь создает запрос на поддержку, данные запроса также проходят через несколько шагов:

  1. Проверка наличия всех обязательных полей.
  2. Валидация данных: проверка корректности email, описания проблемы и т.д.
  3. Удаление лишних пробелов и форматирование текста.
  4. Создание уникального идентификатора запроса.
  5. Сохранение запроса в базу данных.
  6. Отправка уведомления пользователю.
  7. Назначение запроса на поддержку сотруднику.

Эволюция кода

Рассмотрим, как эволюционирует код по мере добавления новых шагов, соблюдая принципы чистой архитектуры и DDD.

Начальная стадия

Сначала у нас есть контроллер и сервис, который выполняет основную логику. Например, простое добавление контакта:

public function store(Request $request, ContactService $contactService)
{
    $contact = $contactService->create($request->all());
    return response()->json($contact, 201);
}

class ContactService
{
    protected $contactRepository;

    public function __construct(ContactRepository $contactRepository)
    {
        $this->contactRepository = $contactRepository;
    }

    public function create(array $data)
    {
        return $this->contactRepository->create($data);
    }
}

class ContactRepository
{
    public function create(array $data)
    {
        return Contact::create($data);
    }
}

Добавление новых шагов

С добавлением новых шагов код становится более сложным. Мы выносим логику в отдельные классы:

public function store(Request $request, ContactService $contactService)
{
    $contact = $contactService->create($request->all());
    return response()->json($contact, 201);
}

class ContactService
{
    protected $contactRepository;

    public function __construct(ContactRepository $contactRepository)
    {
        $this->contactRepository = $contactRepository;
    }

    public function create(array $data)
    {
        $data = (new TrimWhitespace())->handle($data);
        $data = (new ValidateUniqueEmail())->handle($data);
        $data = (new GenerateUniqueId())->handle($data);

        return $this->contactRepository->create($data);
    }
}

Унификация интерфейсов

Мы можем унифицировать интерфейсы и использовать Laravel Pipelines для последовательного выполнения шагов:

public function store(Request $request, ContactService $contactService)
{
    $contact = $contactService->create($request->all());
    return response()->json($contact, 201);
}


class ContactService
{
    protected $contactRepository;

    public function __construct(ContactRepository $contactRepository)
    {
        $this->contactRepository = $contactRepository;
    }

    public function create(array $data)
    {
        $pipes = [
            TrimWhitespace::class,
            ValidateUniqueEmail::class,
            GenerateUniqueId::class,
        ];

        $data = app(Pipeline::class)
            ->send($data)
            ->through($pipes)
            ->then(function ($data) {
                return $this->contactRepository->create($data);
            });

        return $data;
    }
}

Пример использования Laravel Pipelines

Интерфейс Pipe

Каждый шаг (pipe) должен реализовывать интерфейс Pipe:

namespace App\Pipes;

use Closure;

interface Pipe
{
    public function handle($data, Closure $next);
}

Пример шага (Pipe)

namespace App\Pipes;

use Closure;

class TrimWhitespace implements Pipe
{
    public function handle($data, Closure $next)
    {
        $data['name'] = trim($data['name']);
        return $next($data);
    }
}

Сопутствующие проблемы

Иногда на каком-то шаге нужно прервать выполнение или почистить данные в базе данных от выполненных шагов. Пример решения таких проблем:

class ContactService
{
    protected $contactRepository;

    public function __construct(ContactRepository $contactRepository)
    {
        $this->contactRepository = $contactRepository;
    }

    public function create(array $data)
    {
        $pipes = [
            TrimWhitespace::class,
            ValidateUniqueEmail::class,
            GenerateUniqueId::class,
        ];

        try {
            DB::beginTransaction();
            $data = app(Pipeline::class)
                ->send($data)
                ->through($pipes)
                ->then(function ($data) {
                    return $this->contactRepository->create($data);
                });
            DB::commit();
            return $data;
        } catch (Exception $e) {
            DB::rollback();
            throw $e;
        }
    }
}

Здесь используется транзакция для обеспечения целостности данных. В случае ошибки транзакция откатывается (DB::rollback()), и возвращается сообщение об ошибке.

Заключение

Laravel Pipelines – это мощный инструмент для управления последовательными операциями. Он позволяет избежать спагетти-кода и сделать код более чистым и поддерживаемым. В статье мы рассмотрели примеры использования Laravel Pipelines для управления контактами и запросами на поддержку в CRM-системе, соблюдая принципы чистой архитектуры и DDD. Надеемся, что эта информация будет полезной для вас в разработке ваших проектов.

Популярное

Самые популярные посты

Как быть максимально продуктивным на удалённой работе?
Business

Как быть максимально продуктивным на удалённой работе?

Я запустил собственный бизнес и намеренно сделал всё возможное, чтобы работать из любой точки мира. Иногда я сижу с своём кабинете с большим 27-дюймовым монитором в своей квартире в г. Чебоксары. Иногда я нахожусь в офисе или в каком-нибудь кафе в другом городе.

Привет! Меня зовут Сергей Емельянов и я трудоголик
Business PHP

Привет! Меня зовут Сергей Емельянов и я трудоголик

Я программист. В душе я предприниматель. Я начал зарабатывать деньги с 11 лет, в суровые 90-е годы, сдавая стеклотару в местный магазин и обменивая её на сладости. Я зарабатывал столько, что хватало на разные вкусняшки.

Акция! Профессиональный разработчик CRM за 2000 руб. в час

Выделю время под ваш проект. Знания технологий Vtiger CRM, SuiteCRM, Laravel, Vue.js, Golang, React.js, Wordpress. Предлагаю варианты сотрудничества, которые помогут вам воспользоваться преимуществами внешнего опыта, оптимизировать затраты и снизить риски. Полная прозрачность всех этапов работы и учёт временных затрат. Оплачивайте только рабочие часы разработки после приемки задачи. Экономьте на платежах по его содержанию разработчика в штате. Возможно заключение договора по ИП. С чего начать, чтобы нанять профессионального разработчика на full-time? Просто заполните форму!

Telegram
@sergeyem
Telephone
+4915211100235
Email