简体   繁体   English

与Doctrine的QueryBuilder和Symfony2的许多关系

[英]ManyToMany Relationships with Doctrine's QueryBuilder and Symfony2

On a site I'm working on I need to limit results in quite a few places based on a setting for a user. 在我正在处理的网站上,我需要根据用户的设置将结果限制在很多地方。 This is a member on the user called Counties, and is an entity in it's own right. 这是名为Counties的用户的成员,并且是它自己的实体。 I have it set up like this: 我把它设置成这样:

/**
 * @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
}

On my User entity, I have it attached like this: 在我的用户实体上,我有这样的附件:

// ...

/**
 * @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;
}

That all works like it should, and I can attach counties to Users without an issue. 这一切都应该是这样的,我可以毫无问题地将县附加到用户身上。

I then have a second entity called Store which also has these County entities attached to it. 然后我有一个名为Store的第二个实体,它还附有这些County实体。 I did the same declaration but changed the JoinTable name to something different and changed the JoinColumn to use store_id instead of user_id . 我做了相同的声明,但将JoinTable名称更改为JoinTable名称,并将JoinColumn更改为使用store_id而不是user_id By itself, this works just fine. 就其本身而言,这很好用。 I can attach counties to stores. 我可以将县附加到商店。

Now, what I want to do is limit the counties based on the user's counties. 现在,我想要做的是根据用户的县限制县。 For example, if the user is in County A and County B, I only want to see the stores in County A and County B. 例如,如果用户在县A和B县,我只想看到A县和B县的商店。

I cannot figure out how to do that using DQL or the Query Builder. 我无法弄清楚如何使用DQL或查询生成器来做到这一点。 This makes matters worse when I'm trying to use it in a Form, and since I can't get the QueryBuilder syntax correct I can't figure out a way to get the data to limit itself. 当我尝试在Form中使用它时,这会使事情变得更糟,因为我无法使QueryBuilder语法正确,所以我无法找到一种方法来使数据限制自己。

How do you do a QueryBuilder or DQL statement when you have entities set up this way? 当您以这种方式设置实体时,如何执行QueryBuilder或DQL语句?

EDIT 编辑

Here's the SQL statement I'm trying to replicated, for reference: 这是我试图复制的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 

Part of the issue is I'm not sure what should be used. 部分问题是我不确定应该使用什么。 If I add mappedBy or inversedBy, Doctrine complains that the indexes don't exist (because it seems to be looking at the entity tables, not the JoinTable that is declared). 如果我添加mappedBy或inversedBy,Doctrine会抱怨索引不存在(因为它似乎在查看实体表,而不是声明的JoinTable)。 I can't join a table like this because Doctrine complains that there is no association between the two entities: 我无法加入这样的表格,因为Doctrine抱怨两个实体之间没有关联:

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

That makes sense because there is no 'store' member on the County, since it's things like Stores and Users are supposed to have counties, not the other way around, since County is just kind of tag. 这是有道理的,因为县里没有“商店”成员,因为像商店和用户这样的东西应该有县,而不是相反,因为县只是一种标签。

I've even tried this, thinking it would work but didn't have much hope: 我甚至试过这个,认为它会起作用,但没有多少希望:

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

I would switch to just using straight SQL instead of DQL/QueryBuilder, but I'm not sure how to run straight SQL inside of forms, which is a major drawback. 我会切换到只使用直接SQL而不是DQL / QueryBuilder,但我不确定如何在表单中运行直接SQL,这是一个主要缺点。

You can find an example of the proper declaration in the Doctrine documentation 您可以在Doctrine文档中找到适当声明的示例

I've excluded the other annotations on the code sample below 我在下面的代码示例中排除了其他注释

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

This would be the proper annotations and a proper query in an entity repository would be 这将是正确的注释,并且实体存储库中的正确查询将是

 $queryBuilder = $this->createQueryBuilder('c');

 $queryBuilder->select(array('c', 'u'))
              ->leftJoin('c.users', 'u');

 return $queryBuilder->getQuery()->getResult();

It should be exactly the same for the other entity. 对于另一个实体,它应该完全相同。

Thank you Thomas Potaire . 谢谢Thomas Potaire Good example ! 好例子 ! Really helped me. 真的帮到了我。 See below my example queryBuilder. 请参阅下面的示例queryBuilder。 Where string $search, int $locale are. 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');

The Article knows Locale within $locales . Article知道$locales Locale I have also ManyToMany relationship in my project: article -> article_has_locale <- locale 我的项目中也有ManyToMany关系: article - > article_has_locale < - locale

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM