【问题标题】:Need Doctrine Many to Many QueryBuilder Query to Return NOT In Common Rows需要 Doctrine 多对多 QueryBuilder 查询以返回不在公共行中
【发布时间】:2021-05-13 15:51:09
【问题描述】:

我有两张表 1) 价格和 2) 用户

Owner 是价格表中的一列。

两个表在 price.users 和 users.price 之间具有多对多关系。

下面的查询返回 owner1 和 user1 共享的所有价格。

问题:如何解决这个查询,它只返回所有没有与 user1 同步的 owner1 价格。

如果我使用 ->andWhere('u.id = :user1Id') 那么我只会得到 user1 的记录。

如果我使用 ->andWhere('u.id != :user1Id') 那么我会获得所有所有者记录,包括 user1 记录。

再次,我想要所有所有者记录,但与 user1 同步的记录除外。 到目前为止,我已经尝试了以下方法:

1) $queryUsersPrices
                        ->innerJoin('p.owner', 'o')
                        ->leftJoin('p.users', 'u')
                        ->andWhere('o.id = :ownerId')
                        /*I need to Remove records for u.id from results*/
                        ->andWhere('u.id = :user1Id')
                        ->setParameter('owner1Id', $owner->getId())
                        ->setParameter('user1Id', $user->getId());

                    $userPrices = $queryUsersPrices->getQuery()->getResult();

2) $userPrices =   $repository->createQueryBuilder($alias);
                $userPrices
                    ->select("u.prices")
                    ->from("Price","p")
                    ->innerJoin('p.users', 'u')
                    ->andWhere('u.id = :userId')
                    ->getDQL();

   $query = $repository->createQueryBuilder($alias);
                $query
                    ->innerJoin($alias . '.owner', 'o')
                    ->innerJoin($alias . '.priceType', 'pt')
                    ->innerJoin($alias . '.model', 'm')
                    ->where(
                        $query->expr()->not(
                            $query->expr()->in(
                                'p.id',
                                $userPrices
                            )
                        )
                    )
                    ->andWhere('m.status = :m_status')
                    ->andWhere('o.id = :adminId')
                    ->andWhere('pt.site <> 1')
                    ->setParameter('m_status',  Model::STATUS_ACTIVE);

                $result = $query->getQuery()->getResult();

3) $query = $repository->createQueryBuilder($alias);
                $query
                    ->innerJoin($alias . '.owner', 'o')
                    ->innerJoin($alias . '.users', 'u', 'WITH', 'u.id = 
                     :userId')
                    ->innerJoin($alias . '.priceType', 'pt')
                    ->innerJoin($alias . '.model', 'm')
                    ->where('m.status = :m_status')
                    ->andWhere('o.id = :adminId')
                    ->andWhere('u.id IS NULL')
                    ->andWhere('pt.site <> 1')
                    ->setParameter('adminId', $adminUser->getId())
                    ->setParameter('userId',  $user->getId())
                    ->setParameter('m_status',  Model::STATUS_ACTIVE);

                $test = $query->getQuery()->getResult();

方法 #1 只产生用户 1 的价格

方法 #2 导致此错误:错误:方法 Doctrine\Common\Collections\ArrayCollection::__toString() 不得抛出异常,已捕获 Symfony\Component\Debug\Exception\ContextErrorException: Catchable Fatal Error: Object of class Doctrine\ORM\EntityManager 无法转换为字符串

方法 #3 仅产生所有者价格

这实际上是基于 M Khalid Junaid 的回答

$userPrices =   $repository->createQueryBuilder('pr')
                    ->innerJoin('pr.users', 'u')
                    ->andWhere('u.id = :userId')
                    ->setParameter('userId',  $user->getId())
                    ->getDQL();

                $query = $repository->createQueryBuilder($alias);
                $query
                    ->innerJoin($alias . '.owner', 'o')
                    ->innerJoin($alias . '.priceType', 'pt')
                    ->innerJoin($alias . '.model', 'm')
                    ->where(
                        $query->expr()->not(
                            $query->expr()->in(
                                $alias . '.id',
                                $userPrices
                            )
                        )
                    )
                    ->andWhere('m.status = :m_status')
                    ->andWhere('o.id = :adminId')
                    ->andWhere('pt.site <> 1')
                    ->setParameter('m_status',  Model::STATUS_ACTIVE)
                    ->setParameter('adminId', $adminUser->getId())
                    ->setParameter('userId',  $user->getId());

                $result = $query->getQuery()->getResult();

【问题讨论】:

  • 方法 #3 仅产生所有者价格如果这不是您的预期输出,请在结果集中指定您还需要什么

标签: doctrine-orm doctrine doctrine-query


【解决方案1】:

我建议将您的逻辑分解为

首先选择属于$user-&gt;getId()的价格为

$userPrices =   $this->createQueryBuilder("u")
                     ->select("u.prices")
                     ->from("YourBundleName:Prices","p")
                     ->innerJoin('p.users', 'u')
                     ->andWhere('u.id = :user1Id')
                     ->getDQL();

然后获取所有者的价格$owner-&gt;getId(),并从$user-&gt;getId() 的子查询中排除价格

$qb = $this->createQueryBuilder("pr");
 $qb->select("pr")
    ->from("YourBundleName:Price", "pr")
    ->innerJoin('pr.owner', 'o')
    ->where(
        $qb->expr()->not(
            $qb->expr()->in(
            "pr.id",
            $userPrices
            )
        )
    )
    ->andWhere('o.id = :ownerId')
    ->setParameter('owner1Id', $owner->getId())
    ->setParameter('user1Id', $user->getId())
;
$query = $qb->getQuery();
$result = $query->getResult();

这更像是您的原始查询,但不是我猜想的确切查询,可能需要根据您的映射进行一些调整,但会给您一个前进的想法

参考文献

【讨论】:

  • 感谢您的回答。当我尝试使用类似方法时出现此错误:错误:方法 Doctrine\Common\Collections\ArrayCollection::__toString() 不能抛出异常,捕获 Symfony\Component\Debug\Exception\ContextErrorException: Catchable Fatal Error: Doctrine\ORM\EntityManager 类的对象无法转换为字符串
  • @AndreVanVeen 您能否更新您的问题并显示您如何尝试运行此代码的详细信息?这个错误看起来像您没有正确调用它,就像这里提到的stackoverflow.com/questions/33100279/…
  • 请立即查看
  • @AndreVanVeen 你能不能把-&gt;from("Prices","p") 改成-&gt;from("YourBundleName:Prices","p"),除此之外,你还没有通过adminIduserId 等占位符提供值setParameter()
  • 完成!您可能需要更新 $userPrices 查询中的别名以避免 'p' is already defined 错误。非常感谢!
【解决方案2】:

我想通过与 price.users 进行左连接并在连接部分使用附加过滤器子句直接在 DQL 中转换您的逻辑将非常方便,这样它将仅连接用户 ID 为 $user-&gt;getId() 的价格行为了排除这些属于$user-&gt;getId() 的价格,我们可以使用where 子句作为u.id IS NULL

DQL

SELECT p
FROM Price p
JOIN p.owners o 
LEFT JOIN p.users u WITH u.id = :user1Id
WHERE u.id IS NULL
AND o.id = :ownerId

查询生成器会像

$qb =  $this->createQueryBuilder("p")
            ->select("p")
            ->from("Price", "p")
            ->innerJoin('p.owner', 'o')
            ->leftJoin(
                'p.users',
                'u',
                'WITH',
                'u.id = :user1Id'
            )
            ->where('u.id IS NULL')
            ->andWhere('o.id = :ownerId')
            ->setParameter('owner1Id', $owner->getId())
            ->setParameter('user1Id', $user->getId())
        ;
$query = $qb->getQuery();
$result = $query->getResult();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-15
    • 1970-01-01
    相关资源
    最近更新 更多