Учусь.
Стандартный блог (категории, посты, теги).
Подскажите как правильно организовать код. А то какой-то говнокод получается.
В админке есть Posts, Categories, Tags
При нажатии в меню на Posts - вижу все посты
При нажатии в меню на Categories - вижу категории и количество постов к каждой
При нажатии в меню на Tags - вижу теги и количество постов к каждому
При нажатии на количество постов из меню Categories или Tags - попадаю в Posts и вижу соответстующие посты (типа такой фильтр выходит)
Вот по топорному сделал class PostController (такое в контроллере нельзя)
#[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'));
}
Если id категории или тега не переданы, использую findAllOrderedByNewest()
Вместо CategoryRepository и TagRepository - можно написать методы получения соответствующих постов в PostRepository (ща их нет) и убрать CategoryRepository и TagRepository из параметров function index() (и вообще нуужно ли?)
Для постов в PostRepository есть методы.
// 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();
}
Чтобы не использовать CategoryRepository и TagRepository (как говорил выше) можно сюда еще дописать нужные методы.
Это я точно что-то не так делаю. Это ж сколько кода будет (ну можно конечно в методы параметры передавать и по кусочкам внутри собрать запрос, только попробуй потом разберись в этом методе через полгода).
До этого работал на Ларавел, для подобного, кода выходит в разы меньше (есть билдер как тут доктриновский, есть ORM Eloquent где вообще все тремя словами записывается). Здесь не пойму как вообще правильно делается.
Например список постов категории на фронте можно получить через $category->getPosts(), а не через findAllActiveInCategory(), хотя тогда все равно придется писать условия выборки как-то, как?)
Получается в репозиториях вообще все через билдер делается - т.е. обычный sql только запись через билдер?
Как это вообще все делают или как хотя бы это нормально сделать?