Задать вопрос
@Analka

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

Всем привет. Нужен совет - как правильно строить крупный проект?

сейчас создал примерно вот такую структуру проекта:

есть контроллер CategoryController

class CategoryController extends Controller
{
    public function __construct(
        private CategoryService $categoryService
    )
    {
    }
    public function store(CategoryRequest $request)
    {
        return $this->categoryService->store($request->validated());
    }
    public function show(int $id)
    {
        return $this->categoryService->showById($id);
    }
    public function update(CategoryRequest $request, int $id)
    {
        return $this->categoryService->updateById($id, $request->validated());
    }
}


чтобы не плодить кучу кода в контроллере создал сервисный слой

class CategoryService
{
    use JsonResponseTrait;

    public function __construct(
        private CategoryQueryInterface  $categoryQuery,
        private CategoryActionInterface $categoryAction,
    )
    {
    }

    public function store(array $data): JsonResponse
    {
        try {
            $this->categoryAction->store($data);

            return $this->successApiResponse([], Lang::get('database.store_success'));

        } catch (Exception $e) {
            return $this->errorStringApiResponse($e->getMessage(), 500);
        }
    }

    public function showById(int $id): JsonResponse
    {
        $category = $this->categoryQuery->findById($id);

        if (!$category) return $this->notFoundApiResponse([], '404');

        $data = [
            'id' => $category->id,
            'name' => $category->name,
            'icon' => $category->icon,
            'description' => $category->description,
            'metaTitle' => $category->meta_title,
            'metaDescription' => $category->meta_description,
            'isPublished' => $category->is_published,
            'slug' => $category->slug,
            'updatedAt' => $category->updated_at
        ];

        return $this->okApiResponse($data);
    }

    public function updateById(int $id, array $data): JsonResponse
    {
        $model = $this->categoryQuery->findById($id);

        if (!$model) return $this->notFoundApiResponse([], Lang::get('database.record_not_fount'));

        try {
            $this->categoryAction->update($id, $data);

            return $this->successApiResponse([], Lang::get('database.update_success'));

        } catch (Exception $e) {
            return $this->errorStringApiResponse($e->getMessage(), 500);
        }
    }
}


также, чтобы не плодить повторы запросов кода сделать CategoryQuery класс

class CategoryQuery implements CategoryQueryInterface
{
    public function findById(int $id): ?Category
    {
        $query = Category::find($id);

        return $query;
    }
}


+ чтобы как-то отделить создание/редактирование записей сделал CategoryAction

class CategoryAction implements CategoryActionInterface
{

    public function store(array $data): void
    {
        $store = new Category();
        $store->name = trim($data['name']);
        $store->icon = trim($data['icon']);
        $store->description = trim($data['description']);
        $store->text = $data['text'];
        $store->meta_title = $data['metaTitle'] ?? $data['name'];
        $store->meta_description = $data['metaDescription'] ?? $data['metaDescription'];
        $store->is_published = $data['isPublished'];
        $store->slug = trim($data['slug']) ?? Str::slug($data['title'], '-');
        $store->save();
    }

    public function update(Category $category, array $data): void
    {
        $category->name = trim($data['name']);
        $category->icon = trim($data['icon']);
        $category->description = trim($data['description']);
        $category->text = $data['text'];
        $category->meta_title = $data['metaTitle'] ?? $data['name'];
        $category->meta_description = $data['metaDescription'] ?? $data['metaDescription'];
        $category->is_published = $data['isPublished'];
        $category->slug = trim($data['slug']) ?? Str::slug($data['title'], '-');
        $category->save();
    }
}


Вот теперь сижу и думаю, правильно ли я разнес логику, чтобы в дальнейшем проект было легко поддерживать и расширять?
  • Вопрос задан
  • 485 просмотров
Подписаться 2 Простой 4 комментария
Пригласить эксперта
Ответы на вопрос 3
@vism
Называется, услышал звон, да не знаю где он.

1. Сервисный слой ты превратил в контроллер.
Т.е. у тебя есть контроллер, а ты создал ещё один, т.к. где-то слышал, что нужны сервисы.
Но, сервисы не шлют ответы, это внутренний слой для отделения логики.
Ты можешь те методы вызвать через консоль, другие сервисы и т.п.
Там должен просто генерироваться return, а сам response уже в контроллере (чтоб контроллер своб функцию выполнял). Валидацию реквеста кстати тоже надо делать не в сервесе.

2. CategoryQuery - это вобще дичь дикая.
Ты опять создаёшь дубликат, потому что услышал о репозиториях, и даже интерфейс. Вот я угараю с людей, кто везде пихает интерфейсы. Интерфейсы нужны там, где они нужны. Где будет 2+ наследователей интерфейса.
Откуда у тебя тут наследники, если ты завязан на элокуент?
А ноги от индусов репозитаристов. Не нужен репозитарий, Query и интерфейсы при работе в элокуент. Он сам в себе это всё уже содержит и все повторяющиеся вещи обёрнуты уже. find, first, firstOrNew и т.д.
Так что используй элокуент и не переусложняй проект напрасно. Не надо делать сложно, делай просто.

3. CategoryAction.
Опять интерфейс...
Вот это Экшн по сути у тебя сервис. Тут ты имеено перенёс бизнес логику создания и редактирования и возвращаешь ответ данного метода. Вот удали свой CategoryAction и перенеси методы в сервис.
Ответ написан
delphinpro
@delphinpro Куратор тега PHP
frontend developer
метод showById мне кажется вообще лишним.
404 и так вернется если использовать биндинг модели
пересборка атрибутов зачем? просто вернуть модель и всё. ненужные атрибуты скрыть в свойстве $hidden, кастомные добавить в $appends

получится кратко
public function show(Category $category)
{
    return response()->json($category->toArray());
}
Ответ написан
profesor08
@profesor08 Куратор тега PHP
Не не не, сначала строй блок-схему, чтоб иметь визуальное представление того, какие у тебя будут взаимодействия, как будут гулять данные. Так как все со временем забывается, ты всегда сможешь обратиться к ней и вспомнить. Более того, когда ты захочешь что-то поменять, ты это отразишь в блок-схеме, и будешь знать что конкретно надо будет поменять в проекте и, что очень важно, будешь знать как изменяемые части влияют на другие.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы