【问题标题】:Symfony2 and Doctrine2: how to get all tags for a post?Symfony2 和 Doctrine2:如何获取帖子的所有标签?
【发布时间】:2014-12-15 23:47:28
【问题描述】:

在我的项目中,我在两个实体之间存在多对多关系:Post 和 Tag。 (帖子有一个变量“标签”)。

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

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

        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

因此,如果我在搜索表单中输入“chicken egg”,我只需要返回 post1(因为标签)、post2(因为标签)和 post4(因为名称)。

但我还想检索,对于每个帖子,所有相关标签(post1 的烹饪、鸡肉和鸡蛋,...)。

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

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

在我的 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'); 
    }

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

【问题讨论】:

  • 您可以发布分析器生成的 DQL 吗?我也在为你构建一个解决方案,但这会很有帮助。
  • 也想对 SO 表示欢迎。你写了一个很棒的第一个问题,看到它令人耳目一新。
  • 谢谢你的欢迎:)

标签: php symfony doctrine-orm query-builder


【解决方案1】:

你能帮我试一试吗?请注意修改后的方法名称,因为我们正在获取具有多个标签的多个帖子。

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

【讨论】:

  • 非常感谢您的快速回复!它就像一个魅力。不知道这个 'MEMBER OF' 运算符
【解决方案2】:

我认为您在进行参数设置时可能存在错误。您没有用% 包围tag - 这是故意的,因为您希望标签完全匹配吗?此外,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.'%');

【讨论】:

  • 因为如果有多个搜索字符串参数,生成的构建将有多个tagpercent_tag,这是有道理的并且会正确运行,但是我会使用编号参数。跨度>
  • 你会不会只使用编号参数,因为这样的实现看起来更简洁?
  • 没错,但他们最终会做同样的事情。我还认为 OP 有意将通配符排除在标签搜索之外(但不是标题搜索。)
  • 你可能是对的。在这种情况下,您将无法使用编号参数,因为一个使用通配符而另一个没有。
  • for ($i = 0; $i < (count($searchString) * 2); $i = $i + 2) :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
  • 2020-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多