symfony2 doctrine join

时间:2012-04-04 19:37:11

标签: symfony doctrine left-join

好的,所以我有一个查询,我已经研究和研究如何让这个工作和我的生活,我不能!...也许我只是这样做错误和最小的信息ive发现..

我有一个名为timeclock setup的表..它有一个字段:noteBy_id,它是记录所属用户的id ...

我现在需要做的是系统中管理方面的事情。我预计有超过1家公司使用这个时钟系统,因此我需要根据公司ID过滤结果。在用户表中,我有一个名为parentcompany_id

的字段

所以,让我们看看我是否可以用语言表达我需要做的事情。

我需要从时钟中选择*并离开加入user.parentcompany_id,其中timeclock.daydate< :start和u.parentcompany =:pid

其中start是:`date('Y-m-d 00:00:00');

我已设置此查询:

$em = $this->getDoctrine()->getEntityManager();
$start = date('Y-m-d 00:00:00');
$qb = $em->getRepository('EcsCrmBundle:TimeClock');
$qb = $qb->createQueryBuilder('t');

$query = $qb->select('t, u.parentcompany_id')
->from('timeclock', 't')
->leftJoin('Ecs\AgentManagerBundle\Entity\User', 'u', 'ON' 'u.id = t.noteBy_id AND u.parentcompany_id = :pid')
->where('t.daydate < :start')
->andWhere("t.noteBy_id != ''")
->setParameter('start', $start)
->setParameter('pid', $user->getParentcompany())
->getQuery();

$entities = $query->getArrayResult();

我看了看,但找不到我得到的错误的解决方案:

An exception has been thrown during the rendering of a template ("[Semantical Error] line 0, col 112 near 'u ON u.id = t.noteBy_id': Error: Identification Variable Ecs\AgentManagerBundle\Entity\User used in join path expression but was not defined before.") in EcsCrmBundle:TimeClock:manager.html.twig at line 5.

,获取输出的查询是:

SELECT t, u.parentcompany_id FROM Ecs\CrmBundle\Entity\TimeClock t LEFT JOIN Ecs\AgentManagerBundle\Entity\User u ON u.id = t.noteBy_id AND u.parentcompany_id = :pid, timeclock t LEFT JOIN Ecs\AgentManagerBundle\Entity\User u ON u.id = t.noteBy_id AND u.parentcompany_id = :pid WHERE t.daydate < :start AND t.noteBy_id != ''

在正常情况下会完美地工作......但在这方面,它只是没有...任何想法?

2 个答案:

答案 0 :(得分:3)

我最近不得不这样做..我猜这是你的noteBy是用户表中的ManyToOne而你想让它过滤当前管理员公司的结果登录到你的系统..

因此,调整一个我必须自己写这个任务的连接很容易。我个人喜欢使用QueryBuilder,所以这将在查询构建器中完成..

您查询中的第一个错误是->from('timeclock', 't')行。因为您之前使用$qb = $em->getRepository('EcsCrmBundle:TimeClock'); $qb = $qb->createQueryBuilder('t');创建了对象,所以在查询构建器中不需要from,因为它将为您生成。

接下来的问题是左边的问题,我会解释为什么当我向你展示工作版本时。

最后一个问题,即阻止它按你想要的方式工作 - 是一个缺失的andWhere子句。所以,让我们来看看一个有效的查询。

$query = $qb->select('t, u')
     ->leftJoin('t.noteBy', 'u', 'WITH', 'u.id = t.noteBy')
     ->where('t.daydate < :start')
     ->andWhere('u.parentcompany = :pid')
     ->setParameter('start', $start)
     ->setParameter('pid', $user->getParentcompany()) 
     ->getQuery();

因为我们已经使用$qb = $qb->createQueryBuilder('t')创建了对象,我们只需选择tu

对于连接,我们通过noteBy列加入时钟表,该列是用户表中的用户ID。所以,第一个参数是“from”别名。因此,由于我们使用t为时钟表别名,我们使用t.noteBy。 leftjoin中的下一个参数是第二个表的别名,在这种情况下是u但是可以是任何东西..无论如何,leftJoin的第三个参数 - 是你加入它的方式..要么是{{ 1}}或WITH将在这里工作。和第四个参数,是你希望它拥有的匹配......在这种情况下ON

你会看到我摆脱了u.id must equal t.noteBy中的一个,我这样做是因为使用结构合理的查询你不应该需要它。然而,我确实为andWhere添加了andWhere,因为你想要过滤的是你应该在WHERE而不是在连接本身中匹配它。

文档在这方面非常有限,我花了一段时间才把它全部弄清楚..你,毫无疑问 - 像我一样,开始使用学说来手工编写你的查询。因此,你似乎刚刚开始使用Symfony(我现在约2个月),你仍然处于手工编码的心态。但是随着时间的推移,你将开始了解DQL的生活方式。试试这个问题,看看会发生什么。

答案 1 :(得分:0)

好的,首先您需要将实体TimeclockCompany相关联。每当您想要加入Doctrine中的两个实体时,它们需要通过某个属性(即表格列)进行关联。

我认为此查询中不需要User实体,因为所有信息都可以通过Company实体获得,而您不会根据任何用户属性过滤掉结果。

您希望的查询应该看起来像这样(或多或少)。我冒昧并从实体属性中抛弃了_id个后缀,因为它们往往会使实际发生的事情变得模糊。 ;)

$query = $this->getEntityManager()->createQuery("SELECT t, c.id FROM EcsCrmBundle:TimeClock t JOIN t.company c WHERE c.id = :pid AND t.daydate < :start AND t.noteBy != ''");

$query->setParameter('start', $start);
$query->setParameter('pid', $user->getParentcompany());
return $query->getArrayResult();

另外,我做了inner-joinJOIN)因为我认为没有它的公司就没有时钟但是如果你觉得更合适,可以随意改为LEFT JOIN

这是你想要达到的目标吗?