Get children's posts in parents with Doctrine Extensions Tree Nested set

2k views Asked by At

I'm using the nested set behaviour in Symfony2 with StofDoctrineExtension.

The category and post model are well configured, and the category tree works fine.

To show the posts of a category I use this query from my repository:

public function findAllPosts($category)
{
    return $this->queryAllPosts($category)->getResult();
}

public function queryAllPosts($category)
{
    $em = $this->getEntityManager();

    $query = $em->createQuery('
        SELECT p, c FROM AppBundle:Post p JOIN p.category c
        WHERE c.slug = :category
        ORDER BY p.created DESC
    ');

    $query->setParameter('category', $category);

    return $query;
}

But how could I do to show the posts of the children of the categories too?

3

There are 3 answers

0
Diego On BEST ANSWER

I found the way. The query would be like this:

/*
 * GET POSTS FROM PARENT AND CHILDREN
 */
public function getPostsParentAndChildren($children)
{
    $em = $this->getEntityManager();

    $posts = $em->createQueryBuilder()
        ->select(array('p', 'c'))
        ->from('AppBundle:Post', 'p')
        ->join('p.category', 'c')
        ->where('c.id IN (:children)')
        ->orderBy('p.created', 'DESC')
        ->getQuery();

    $posts->setParameter('children', $children);

    return $posts->getResult();
}

We pass an array with the children to the query, which we obtain with the function getChildren($categoryId). Remember that you have to pass the id (with this query), so you could get the ids like this:

    $category = $repo->findOneBy(array('slug' => $slug1));

    $children = $repo->getChildren($category);

    $childrenIds[] = $category->getId();
    foreach ($children as $child){
        $id = $child->getId();
        $childrenIds[] = $id;
    }

    $posts = $em->getRepository('AppBundle:Category')->getPostsParentAndChildren($childrenIds);
2
Nawfal Serrar On

You should be able to do this in one query which will be close to this one as i am not pro SQL it usually takes me time and tests before i get it right but this is where i would start :

 SELECT parent.* , children.* FROM 
          (SELECT p, c FROM AppBundle:Post p JOIN p.category c WHERE c.slug = :category) AS parent 
          INNER JOIN 
          (SELECT p1 FROM  AppBundle:Post p1 JOIN p.category c1 ON c1.parent = parent.id ) AS children 

not sure if you need to do the ON inside the inner select or the wrapper select for the join but you can try :)

0
Jean D. On

If your CategoryRepository inherits from NestedTreeRepository you could do something like this:

$categories = $em->getRepository('XBundle:Category')
  ->childrenQueryBuilder($category)
  ->addSelect('posts')
  ->join('node.posts', 'posts')
  ->getQuery()
  ->getResult();

foreach ($categories as $category) {
  $category->getPosts();
  // do stuff
}