@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();
    }
}


Вот теперь сижу и думаю, правильно ли я разнес логику, чтобы в дальнейшем проект было легко поддерживать и расширять?
  • Вопрос задан
  • 484 просмотра
Пригласить эксперта
Ответы на вопрос 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
Не не не, сначала строй блок-схему, чтоб иметь визуальное представление того, какие у тебя будут взаимодействия, как будут гулять данные. Так как все со временем забывается, ты всегда сможешь обратиться к ней и вспомнить. Более того, когда ты захочешь что-то поменять, ты это отразишь в блок-схеме, и будешь знать что конкретно надо будет поменять в проекте и, что очень важно, будешь знать как изменяемые части влияют на другие.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
19 апр. 2024, в 03:52
1000 руб./за проект
19 апр. 2024, в 03:01
1000 руб./за проект
18 апр. 2024, в 21:56
2000 руб./за проект