Symfony2和Doctrine2:如何获取帖子的所有标签?

时间:2022-09-15 20:12:29

In my project, I have a many-to-many relationship between two entities: Post and Tag. (Post has a variable 'tags').

在我的项目中,我在两个实体之间存在多对多关系:Post和Tag。 (Post有一个变量'tags')。

I want to allow the user to search posts through their name OR their tags (like on tumblr for exemple)

我想允许用户通过他们的名字或他们的标签来搜索帖子(比如tumblr上的例子)

Let's say I have this in my database:

假设我在我的数据库中有这个:

        Name                     Tags
post1: "Recipe with eggs"        cooking, chicken, egg    
post2: "Random Title"            beef, chicken, egg    
post3: "Cooking Fish"            fish, cooking
post4: "Rice and chicken"        rice, meat

So if I enter 'chicken egg' in my search form, I have to return only post1 (because of the tags), post2 (because of the tags) AND post4 (because of the name).

因此,如果我在搜索表单中输入“鸡蛋”,我必须只返回post1(因为标签),post2(因为标签)和post4(因为名称)。

But I also want to retrieve, for each post, all their associated tags (cooking, chicken and egg for post1, ...).

但是我也希望为每个帖子检索所有相关的标签(post1的烹饪,鸡肉和鸡蛋......)。

In my Controller, I have this:

在我的控制器中,我有这个:

//$data['search'] comes from a form and contains for exemple 'chicken egg'
$searchString = $data['search'];
$searchString = explode(' ',$searchString);
$list = $repository->getPostByTag($searchString);

In my PostRepository.php I have created this:

在我的PostRepository.php中我创建了这个:

    public function getPostByTag($searchString)
    {
        $query = $this->createQueryBuilder('p')->leftJoin('p.tags','t');
        $i = 0;
        foreach($searchString as $tag)
        {
           $query->orWhere('t.name like :tag'.$i.' OR p.name like :percent_tag'.$i)
              ->setParameter('tag'.$i, $tag)
              ->setParameter(':percent_tag'.$i,'%'.$tag.'%');
           $i++;
        }
        $query->leftJoin('p.author','a')
              ->leftJoin('p.tags','t2')
              ->addSelect('t2')
              ->addSelect('a'); 
    }

But this "getPostByTag" method gives me very random results... How can I get every posts and their associated tags by searching through their name and theirs tags?

但是这个“getPostByTag”方法给了我非常随机的结果......如何通过搜索他们的名字和他们的标签来获得每个帖子及其相关标签?

2 个解决方案

#1


1  

Can you give this one a whirl for me? Note the modified method name due to the fact that we're fetching multiple Posts with multiple Tags.

你能给我这个旋转吗?请注意修改后的方法名称,因为我们正在使用多个标记获取多个帖子。

public function getPostsByTags($tagArray = array()) {
    $query = $this->createQueryBuilder('p');
    $i = 1;
    $tagObjects = this->getEntityManager()->getRepository('AcmeBundle:Tag')
        ->findByName(array('name' => $tagArray)); // This is case-insensitive by default

    foreach ($tagObjects as $tagObj) {
        $query->orWhere('?'.$i.' MEMBER OF p.tags')->setParameter($i, $tagObj);
        $i++;
    }

    foreach ($tagArray as $tag) {
        $query->orWhere('p.name LIKE ?'.$i)->setParameter($i, '%'.$tag.'%');
        $i++;
    }

    $query->leftJoin('p.tags', 't')
        ->leftJoin('p.author', 'a')
        ->addSelect('t')->addSelect('a')
        ->getQuery();

    return $query->getResult();
}

#2


0  

I think you might have an error in how you are doing your parameter settings. You don't surround tag with % - was that intentional because you want tags to match exactly? Also you shouldn't have the : for the percent_tag.

我想您在参数设置方面可能会出错。您没有使用%环绕标记 - 这是故意的,因为您希望标记完全匹配吗?你也不应该有:for percent_tag。

$query->orWhere('t.name like :tag'.$i.' OR p.name like :percent_tag'.$i)
   ->setParameter('tag'.$i, $tag)
   ->setParameter('percent_tag'.$i,'%'.$tag.'%');

#1


1  

Can you give this one a whirl for me? Note the modified method name due to the fact that we're fetching multiple Posts with multiple Tags.

你能给我这个旋转吗?请注意修改后的方法名称,因为我们正在使用多个标记获取多个帖子。

public function getPostsByTags($tagArray = array()) {
    $query = $this->createQueryBuilder('p');
    $i = 1;
    $tagObjects = this->getEntityManager()->getRepository('AcmeBundle:Tag')
        ->findByName(array('name' => $tagArray)); // This is case-insensitive by default

    foreach ($tagObjects as $tagObj) {
        $query->orWhere('?'.$i.' MEMBER OF p.tags')->setParameter($i, $tagObj);
        $i++;
    }

    foreach ($tagArray as $tag) {
        $query->orWhere('p.name LIKE ?'.$i)->setParameter($i, '%'.$tag.'%');
        $i++;
    }

    $query->leftJoin('p.tags', 't')
        ->leftJoin('p.author', 'a')
        ->addSelect('t')->addSelect('a')
        ->getQuery();

    return $query->getResult();
}

#2


0  

I think you might have an error in how you are doing your parameter settings. You don't surround tag with % - was that intentional because you want tags to match exactly? Also you shouldn't have the : for the percent_tag.

我想您在参数设置方面可能会出错。您没有使用%环绕标记 - 这是故意的,因为您希望标记完全匹配吗?你也不应该有:for percent_tag。

$query->orWhere('t.name like :tag'.$i.' OR p.name like :percent_tag'.$i)
   ->setParameter('tag'.$i, $tag)
   ->setParameter('percent_tag'.$i,'%'.$tag.'%');