与学说的许多关系;的QueryBuilder和Symfony2


ManyToMany Relationships with Doctrine's QueryBuilder and Symfony2

在我正在开发的网站上,我需要根据用户的设置将结果限制在相当多的地方。这是一个名为Counties的用户的成员,并且是一个独立的实体。我把它设置成这样:

/**
 * @ORM'Entity
 * @ORM'Table(name="county")
 */
class County
{
    /**
     * @ORM'Id
     * @ORM'Column(type="integer")
     * @ORM'GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @var string
     * @ORM'Column(type="string")
     */
    protected $name;
    // ... Getters and Setters
}

在我的用户实体上,我有这样的附件:

// ...
/**
 * @ORM'ManyToMany(targetEntity="App'Bundle'UserBundle'Entity'County")
 * @ORM'JoinTable(name="user_county_xref",
 *      joinColumns={@ORM'JoinColumn(name="user_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM'JoinColumn(name="county_id", referencedColumnName="id")}
 * )
 */
protected $counties;
// ...
/**
 * Add counties
 *
 * @param 'App'Bundle'UserBundle'Entity'County $counties
 * @return User
 */
public function addCountie('App'Bundle'UserBundle'Entity'County $counties)
{
    $this->counties[] = $counties;
    return $this;
}
/**
 * Remove counties
 *
 * @param 'App'Bundle'UserBundle'Entity'County $counties
 */
public function removeCountie('App'Bundle'UserBundle'Entity'County $counties)
{
    $this->counties->removeElement($counties);
}
/**
 * Get counties
 *
 * @return 'Doctrine'Common'Collections'Collection 
 */
public function getCounties()
{
    return $this->counties;
}

这一切都正常工作,我可以毫无问题地将县附加到用户。

然后我有一个名为Store的第二个实体,它也附加了这些County实体。我做了同样的声明,但将JoinTable的名称更改为不同的名称,并将JoinColumn更改为使用store_id而不是user_id。就其本身而言,这很好。我可以把县和商店联系起来。

现在,我想做的是根据用户的县来限制县。例如,如果用户在县A和县B,我只想看到县A和郡B的商店。

我不知道如何使用DQL或查询生成器来做到这一点。当我试图在表单中使用它时,情况会变得更糟,而且由于我无法获得正确的QueryBuilder语法,我无法找到一种方法来限制数据本身。

当以这种方式设置实体时,如何执行QueryBuilder或DQL语句?

编辑

以下是我试图复制的SQL语句,供参考:

SELECT S.* 
FROM store S 
JOIN store_county_xref SCX 
    ON SCX.store_id=S.id 
JOIN user_county_xref UCX 
    ON UCX.county_id=RCX.county_id 
WHERE UCX.user_id = 1 

问题的一部分是我不确定应该使用什么。如果我添加mappedBy或invertedBy,Doctrine会抱怨索引不存在(因为它看起来是在看实体表,而不是声明的JoinTable)。我不能加入这样的表格,因为Doctrine抱怨这两个实体之间没有关联:

SELECT s 
FROM AppStoreBundle:Store s 
JOIN AppUserBundle:County c WITH c.store = s.id

这是有道理的,因为郡上没有"商店"成员,因为商店和用户应该有郡,而不是相反,因为郡只是一种标签。

我甚至尝试过,认为它会起作用,但没有太大希望:

SELECT s 
FROM AppStoreBundle:Store s 
JOIN AppUserBundle:User u WITH u.counties = s.counties

我会改用直接SQL而不是DQL/QueryBuilder,但我不确定如何在表单中运行直接SQL,这是一个主要缺点。

您可以在条令文档中找到正确声明的示例

我已经排除了下面代码示例上的其他注释

class County
{
    /**
     * @ManyToMany(targetEntity="User", mappedBy="counties")
     **/
    protected $users;
 }
 class User
 {
      /**
       * @ORM'ManyToMany(targetEntity="App'Bundle'UserBundle'Entity'County", inversedBy="users")
       * @ORM'JoinTable(name="user_county_xref",
       *      joinColumns={@ORM'JoinColumn(name="user_id", referencedColumnName="id")},
       *      inverseJoinColumns={@ORM'JoinColumn(name="county_id", referencedColumnName="id")}
       * )
       */
      protected $counties;
 }

这将是正确的注释,实体存储库中的正确查询将是

 $queryBuilder = $this->createQueryBuilder('c');
 $queryBuilder->select(array('c', 'u'))
              ->leftJoin('c.users', 'u');
 return $queryBuilder->getQuery()->getResult();

对于其他实体,它应该完全相同。

谢谢Thomas Potaire。好榜样!真的帮了我。请参阅下面的queryBuilder示例。其中string $search, int $locale为。

$q  = $qb->select(array('a'))
                ->from(Article::class, 'a')
                ->leftJoin('a.locales', 'l')
                ->where(
                    $qb->expr()->like('a.articleName',"'%$search%'")
                )
                ->andWhere('l.id = '.$locale)
                ->orderBy('a.id', 'DESC')
                ->getQuery();
            $articles= $q->getResult();
            if ($articles==null)
                throw new 'Exception('Article with key '.$search.' not found');

Article知道$locales中的Locale。我在我的项目中也有很多关系:article->article_has_locale<-区域设置