选择多个实体原则

时间:2016-01-05 03:50:18

标签: symfony doctrine-orm

我正在尝试执行以下查询:

$qb = $this->getEntityManager()->createQueryBuilder();
$referredUsers = $qb->select(['referred', 'referral', 'match'])
    ->from('ProjectContestBundle:UserParticipation', 'up')
    ->innerJoin('ProjectUserBundle:User', 'referred', 'WITH', 'up.user = referred')
    ->innerJoin('ProjectUserBundle:User', 'referral', 'WITH', 'up.referral = referral.referralCode')
    ->innerJoin('ProjectContestBundle:UserParticipation', 'upr', 'WITH', 'upr.user = referral')
    ->innerJoin('ProjectMatchBundle:Match', 'match', 'WITH', 'match.owner = referred')
    ->where('up.contest = :contest')->andWhere('upr.contest = :contest')
    ->setParameter('contest', $contest)
    ->getQuery()->getResult();

我期待一个行数组,其中每一行的类型为[User, User, Match],但Doctrine会返回一个包含实体混合内容的普通数组。

然后我尝试用以下方法简化:

$qb = $this->getEntityManager()->createQueryBuilder();
$referredUsers = $qb->select(['referred.id', 'referral.id', 'match.id'])
    ->from('ProjectContestBundle:UserParticipation', 'up')
    ->innerJoin('ProjectUserBundle:User', 'referred', 'WITH', 'up.user = referred')
    ->innerJoin('ProjectUserBundle:User', 'referral', 'WITH', 'up.referral = referral.referralCode')
    ->innerJoin('ProjectContestBundle:UserParticipation', 'upr', 'WITH', 'upr.user = referral')
    ->innerJoin('ProjectMatchBundle:Match', 'match', 'WITH', 'match.owner = referred')
    ->where('up.contest = :contest')->andWhere('upr.contest = :contest')
    ->setParameter('contest', $contest)
    ->getQuery()->getResult();

会产生[{"id":1},{"id":2},{"id":3},{"id":4}]。如果我在数据库上运行查询它可以正常工作:

SELECT u0_.ID AS ID0, u1_.ID AS ID1, m2_.ID AS ID2 FROM UserParticipation u3_ INNER JOIN users u0_ ON (u3_.user_id = u0_.ID) INNER JOIN users u1_ ON (u3_.l = u1_.referralCode) INNER JOIN UserParticipation u4_ ON (u4_.user_id = u1_.ID) INNER JOIN matches m2_ ON (m2_.ownerID = u0_.ID) AND (m2_.deletedAt IS NULL) WHERE u3_.contest_id = 1 AND u4_.contest_id = 1;

返回:

+-----+-----+-----+
| ID0 | ID1 | ID2 |
+-----+-----+-----+
|   1 |   9 |   1 |
|   1 |   9 |   2 |
|   1 |   9 |   3 |
|  10 |   9 |   4 |
+-----+-----+-----+

所以我尝试添加一些as和:

$referredUsers = $qb->select(['referred.id as r1', 'referral.id as r2', 'match.id as m'])
    ->from('ProjectContestBundle:UserParticipation', 'up')
    ->innerJoin('ProjectUserBundle:User', 'referred', 'WITH', 'up.user = referred')
    ->innerJoin('ProjectUserBundle:User', 'referral', 'WITH', 'up.referral = referral.referralCode')
    ->innerJoin('ProjectContestBundle:UserParticipation', 'upr', 'WITH', 'upr.user = referral')
    ->innerJoin('ProjectMatchBundle:Match', 'match', 'WITH', 'match.owner = referred')
    ->where('up.contest = :contest')->andWhere('upr.contest = :contest')
    ->setParameter('contest', $contest)
    ->getQuery()->getArrayResult();

,结果是正确的!

[{"r1":1,"r2":9,"m":1},{"r1":1,"r2":9,"m":2},{"r1":1,"r2":9,"m":3},{"r1":10,"r2":9,"m":4}]

如果我尝试使用非id版本返回,留下as我仍然会返回一行行,其中每行是不同的实体,但是我希望有一行{{1如select所示(与MySql原始结果相同,仅与实体相同)。

1 个答案:

答案 0 :(得分:2)

简短回答

教义只选择水合物作为关系。

长答案

默认情况下,Doctrine返回“from entity”作为查询的所有者。我的意思是,它将返回此实体的数组,并且它将根据您的映射填充此实体内的其余实体。

我建议您将up.referraluser.referralCode更改为关系而不是列。另一个变化是地图用户访问匹配(如果它是一对一的关系)。

让我们简化一下代码:

$qb = $this->getEntityManager()->createQueryBuilder();

//it will return array of UserParticipation
$userParticipations = $qb->select('up, referred, match')
    ->from('ProjectContestBundle:UserParticipation', 'up')
    ->innerJoin('up.user','referred')
    ->innerJoin('up.referralUser', 'referral')
    ->innerJoin('referred.match', 'match')
    ->where('up.contest = :contest')
    ->setParameter('contest', $contest)
    ->getQuery()->getResult();

$userParticipations数组中的每个项目都是UserParticipation。您可以通过它访问引荐的($userParticipations[0]->getUser()),引荐($userParticipations[0]->getReferralUser()),匹配($userParticipations[0]->getUser()->getMatch()),等等。

这几乎是你的第一次尝试。

注意以上代码仅在您对地图和数据库进行一些更改时才有效。