A
A
Alexey2021-12-07 09:30:31
symfony
Alexey, 2021-12-07 09:30:31

Repository, how to organize requests of the same type?

I study.
Standard blog (categories, posts, tags).
Please tell me how to organize the code. And then some kind of govnokod turns out.

There are Posts, Categories, Tags in the admin panel
When I click on the Posts menu - I see all posts
When I click on the Categories menu - I see categories and the number of posts for each
When I click on Tags in the menu - I see tags and the number of posts for each
When I click on the number posts from the Categories or Tags menu - I get to Posts and see the corresponding posts (like such a filter comes out

)

#[Route('', name: 'index', methods: ['GET'])]
public function index(
    PostRepository $postRepository,
    CategoryRepository $categoryRepository,
    TagRepository $tagRepository,
    Request $request,
    PaginatorInterface $paginator
): Response {
    if ($category = $request->query->getInt('category')) {
        $category = $categoryRepository->find($category);
        $posts = $category
            ? $category->getPosts()
            : $postRepository->findAllOrderedByNewest();
    } elseif ($tag = $request->query->getInt('tag')) {
        $tag = $tagRepository->find($tag);
        $posts = $tag
            ? $tag->getPosts()
            : $postRepository->findAllOrderedByNewest();
    } else {
        $posts = $postRepository->findAllOrderedByNewest();
    }

    $posts = $paginator->paginate($posts, $request->query->getInt('page', 1));

    return $this->render('admin/blog/post/index.html.twig', compact('posts'));
}

If the category or tag id is not passed, I use findAllOrderedByNewest()
Instead of CategoryRepository and TagRepository - you can write methods for getting the corresponding posts in the PostRepository (there are none) and remove the CategoryRepository and TagRepository from the function index() parameters (and is it generally necessary?)

For posts PostRepository has methods.
// PostRepository

// Для получения списка в админке
public function findAllOrderedByNewest()
{
    return $this->createQueryBuilder('p')
        ->leftJoin('p.category', 'c')
        ->addSelect('c')
        ->leftJoin('p.tags', 't')
        ->addSelect('t')
        ->orderBy('p.createdAt', 'DESC')
        ->getQuery()
        ->getResult();
}
// Для получения списка активных на фронте
public function findAllActiveOrderedByNewest()
{
    return $this->createQueryBuilder('p')
        ->leftJoin('p.category', 'c')
        ->addSelect('c')
        ->leftJoin('p.tags', 't')
        ->addSelect('t')
        ->andWhere('p.isActive = true')
        ->andWhere('c.isActive = true')
        ->orderBy('p.createdAt', 'DESC')
        ->getQuery()
        ->getResult();
}
// Для получения одного поста на фронте
public function findOneActiveBySlug(string $slug): ?Post
{
    return $this->createQueryBuilder('p')
        ->select('p', 'c')
        ->where('p.slug = :slug')
        ->setParameter('slug', $slug)
        ->leftJoin('p.category', 'c')
        ->andwhere('p.isActive = true')
        ->andWhere('c.isActive = true')
        ->setMaxResults(1)
        ->getQuery()
        ->getOneOrNullResult();
}
// Для получения списка постов категории на фронте
public function findAllActiveInCategory(Category $category)
{
    return $this->createQueryBuilder('p')
        ->select('p', 't')
        ->leftJoin('p.tags', 't')
        ->where('p.category = :category')
        ->setParameter('category', $category)
        ->andWhere('p.isActive = true')
        ->orderBy('p.createdAt', 'DESC')
        ->getQuery()
        ->getResult();
}

In order not to use CategoryRepository and TagRepository (as mentioned above), you can add the necessary methods here.
It's definitely something I'm doing wrong. Well, this is how much code there will be (well, of course, you can pass parameters to the methods and collect the request piece by piece inside, just try to understand this method later in six months).

Before that, I worked on Laravel, for this, the code comes out many times less (there is a builder like Doctrine here, there is an ORM Eloquent where everything is generally written in three words). I don't understand how to do it right here.

For example, a list of category posts on the front can be obtained through $category->getPosts(), and not through findAllActiveInCategory(), although then you still have to write the selection conditions somehow, how?)

It turns out in the repositories, in general, everything is done through the builder - i.e. normal sql only record through builder?
How does everyone do it, or at least how to do it normally?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
H
heartdevil, 2021-12-07
@heartdevil

I don't know laravel or symfony, but maybe I can help you with ideas.
There will most likely be more code, simply because you write everything yourself. It can become less only if you install something in the symphony there and use this add-on. But ideologically, you already have a division into repositories and you need another layer of business logic. You can also store business logic in repositories, but then the question is, why do we need this layer of repositories at all, if everything can be stored in controllers :). In general, repositories should be as general as possible. Some simple requests to the type base, return everything or return everything whose id is equal to something. Things like flags or sorting can also be built into queries right away, but usually flags are already business logic. As well as some custom sorting. For such "tricky" requests, one more layer is usually allocated. Business logic. For example, we call it Services and forward our repositories there and on the basis of them methods like GetActiveSoretedFilteredAndSoOnService are already being made. Well, then the services are forwarded to the controllers and the controllers only know about them. You are right about controllers. It is better not to keep such switching logic there. Although it happens differently. And the question is, why switch requests in the controller like that? What is the benefit? Maybe it's better to make a separate get method in the controller for each menu item? Or is it symfony specific? That everything must be done through the index. And the question is, why switch requests in the controller like that? What is the benefit? Maybe it's better to make a separate get method in the controller for each menu item? Or is it symfony specific? That everything must be done through the index. And the question is, why switch requests in the controller like that? What is the benefit? Maybe it's better to make a separate get method in the controller for each menu item? Or is it symfony specific? That everything must be done through the index.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question