запутался, или пытаюсь переусложнить.
В проекте мне нужно создавать различные отчеты, на основе которых будут происходить различные действия. Например, отчет о перемещении товара -> переместили товар. Отчет не равно действие, так как не все пользователи и не все отчеты предполагают моментальное исполнение - могут требовать подтверждения другим пользователем.
Сейчас реализовано так:
- Абстрактный Report (наследуется от Model), тут общие атрибуты для всех отчетов
- Наследующиеся от него Report[ТипОтчета], со своими атрибутами (хотя полагаю, что надо заменить на [ТипОтчета]Report)
- ReportController отдает нужные view или передает Request в ReportService (на самом деле public function store(ReportService $service) { ... $service->store(); ... })
- ReportService производит нужные действия - регистрирует отчет, позволяет заполнить его данными последовательно или сразу (тут два вида интерфейса, отсюда вариативность) и сохраняет отчет
Вопросы:
- Где стоит разместить функционал преобразования отчета в действие? Логично ли это сделать в Report как apply() и перезаписывать её в отчетах (public для вызова, внутри private, естественно)?
- Стоит ли выполнять действие напрямую $report->storageLocation->addInventory($report->storageItem, $report->quantity), или тут нужны Actions?
- Как вызывать её автоматически после создания для отдельных видов отчетов? Observer, Event, вызывать сразу из ReportService?
- Возможно, есть более логичный способ?
Заранее спасибо :)
1. Возможно, нужна прослойка из сервисного слоя 2. Actions нужны, полагаю, для чистоты кода 3. Observer, Event , Queue, как решите 4. Думаю, что нет
всё зависит от того, как именно хотите автоматизировать процесс и как реализована архитектура БД, много нюансов
Огромное спасибо за ответ :) Немного уточню: 1. Что-то вроде ReportApplyService, верно понял? Не могу пока понять, что он будет делать.. По итогу же все равно придется вызывать метод конкретного отчета. 2. Принял 3. Хм. Полагаю, что для гомогенности с ручным проведением, больше подходит Queue, спасибо! 4. 👍 С сервисной прослойкой пока не понял, предполагаю вот так: Класс ProcessReport (ShouldQueue), диспатчим с нужным Report, а вот дальше как пробросить до нужного экшна не понял. Всё так же возвращаюсь к методу модели Report - не будет ли это нарушением конвенций? Архитектуру БД стараюсь держать максимально простой, то есть все модели и связи реализованы родными средствами фреймворка - отсюда у меня и вопросы, раньше писал много спагетти-кода, сейчас хочу обойтись без велосипедов.
Вообще лучше, думаю поделить отчёты на разные классы, чтобы не держать все в Report, иначе разрастание будет дикое, в каждом Action прокидываем нужный тип, можно и создать enum, если их немного и с помощью как раз разных типов Report организовывать разные проверки и бизнес-логику
Так они как раз и есть в разных классах и наследуются от Report. У каждого свой тип Enum есть, пока используется для авторегистрации всех типов отчетов. Отсюда я и думаю про public Report->apply() который обращается к private $this->applyReport(), который уже у каждого класса отчета свой, и ссылается на нужный Action.
Обсуждают сегодня