symfony2 学说加入

Posted

技术标签:

【中文标题】symfony2 学说加入【英文标题】:symfony2 doctrine join 【发布时间】:2012-04-04 19:37:10 【问题描述】:

好的,所以我有一个查询,我已经研究并研究了如何让它工作,而我这辈子做不到!...也许我只是做错了,而且我得到的信息很少找到了..

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

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

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

我需要从时钟中选择 * 并离开加入 user.parentcompany_id where timeclock.daydate

开始是:`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 个 LEFT JOINS 而不是 1 个...所以谁知道真正的问题在哪里... 在以下人员的帮助下:***.com/questions/9399355/… 我解决了这个问题..... 【参考方案1】:

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

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

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

下一个问题是 leftJoin,当我向您展示工作版本时,我会解释原因。

最后一个问题,阻止它按你的意愿工作 - 是缺少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-&gt;createQueryBuilder('t') 创建了对象,所以我们只需选择tu

对于连接,我们通过noteBy 列连接时钟表,这是用户表中的用户ID。因此,第一个参数是“来自”别名。因此,由于我们使用 t 为时钟表起别名,我们使用 t.noteBy。 leftjoin 中的下一个参数是第二个表的别名,在这种情况下是u,但可以是任何东西。无论如何,leftJoin 的第三个参数 - 是你加入它的方式。@ 987654332@ 或ON 将在这里工作。第四个参数是您希望它拥有的匹配项。在这种情况下u.id must equal t.noteBy

您会看到我删除了andWhere 之一,我这样做是因为使用结构正确的查询您不需要它。但是,我确实为 u.parentcompany 添加了 andWhere,因为毕竟这是您要过滤的内容,您应该将其放在 WHERE 中,而不是作为连接本身的匹配项。

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

【讨论】:

【参考方案2】:

好的,首先您需要将实体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-join (JOIN),因为我认为没有它的陪伴就不可能有时钟,但如果更适合您,请随时将其更改为 LEFT JOIN

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

【讨论】:

公司实体与用户实体一样位于另一个 Bundle 中。无论如何,对我而言,您的解决方案的问题是 TimeClock 表引用了用户的 ID,因此是用户表里面有父公司而不是时钟表。所以我必须使用用户表来过滤当前登录的经理公司的结果......

以上是关于symfony2 学说加入的主要内容,如果未能解决你的问题,请参考以下文章

学说查询的语法错误 (Symfony2)

Symfony2 和空关系的学说

未定义索引:joinColumns 学说 + symfony2

Symfony2 学说清除缓存

Symfony2:学说“找不到驱动程序”

Symfony2 - 学说:模式:更新失败,实体在包之外(解耦)