查询构建器加入一对多关系

时间:2013-03-05 11:08:04

标签: symfony doctrine-orm

我有一个与我的用户对象有多对一关系的LastTrait对象:一个用户可以有许多不同的lastTrait:

YOP\YourOwnPoetBundle\Entity\LastTrait:
  type: entity
  table: null
  fields:
id:
  type: integer
  id: true
  generator:
    strategy: AUTO
traitCategoryID:
  type: integer
verseID:
  type: integer
  manyToOne:
user:
  targetEntity: User
  inversedBy: lastTrait
  joinColumn:
      name: user_id
      referencedColumnName: id

我需要在知道userID和traitCategoryID的情况下检索verseID。所以我为我的LastTrait对象创建了一个Repository:

<?php

namespace YOP\YourOwnPoetBundle\Repository;

use Doctrine\ORM\EntityRepository;

class LastTraitRepository extends EntityRepository {

public function findOneByTraitCategoryID($userID, $traitCategoryID)
{
    return $this->getEntityManager()
    ->createQuery('SELECT l
        FROM YOPYourOwnPoetBundle:LastTrait l
        JOIN l.user u
        WHERE l.traitCategoryID = :categoryID AND u.id = :userID')
    ->setParameters(array(
        'categoryID' => $traitCategoryID,
        'userID' => $userID,
    ))
    ->getResult();
}
}

?>

然而,当我打电话时:

$lastTrait = $this->getDoctrine()
        ->getRepository('YOPYourOwnPoetBundle:LastTrait')
        ->findOneByTraitCategoryID($user->getID(), $collector->getTraitCategory()->getID());

我总是得到NULL,即使我应该得到一个LastTrait对象!

我在这里做错了什么?

3 个答案:

答案 0 :(得分:1)

我认为你应该在实体中考虑更多,而在外键中考虑更少。

在您的方法中尝试此操作。

public function findOneByTraitCategoryID($userID, $traitCategoryID)
{
     return $this->findOneBy(
            array(
            'traitcategoryID' => $traitCategoryID,
            'user' => $userID
            ));
}

你可以调用 - &gt; getVerse() - &gt; getId();在此之后或直接在方法上返回id(对于将来使用IMO而言太窄)。

仅当用户每个类别只有一个特征时才有效,否则您没有足够的数据来获取特定特征。

答案 1 :(得分:1)

问题是我忘了在我的实体中注册存储库:

YOP\YourOwnPoetBundle\Entity\LastTrait:
  repositoryClass: YOP\YourOwnPoetBundle\Repository\LastTraitRepository
  type: entity
  table: null
  fields:
id:
  type: integer
  id: true
  generator:
    strategy: AUTO
traitCategoryID:
  type: integer
verseID:
  type: integer
  manyToOne:
user:
  targetEntity: User
  inversedBy: lastTrait
  joinColumn:
      name: user_id
      referencedColumnName: id

添加repositoryClass行后,我的自定义Repository类被调用,我得到了所需的结果。

然而,@ dhunter的回答让我意识到我甚至不需要自定义Repository类。只需使用我的控制器中的常规findOneBy函数,我就可以得到所需的东西:

$lastTrait = $this->getDoctrine()
  ->getRepository('YOPYourOwnPoetBundle:LastTrait')
  ->findOneBy(
      array('user' => $user->getId(), 'traitCategoryID' => $collector->getTraitCategory()->getID())
  );

答案 2 :(得分:0)

很难说。在返回结果之前尝试回显DQL或SQL:

$q = $this->getEntityManager()->createQuery(....);
die($q->getSql()); //or getDql();

如果出于某种原因,您的映射无效(我上面没有看到),您应该在这里看到它。

另外,尝试使用try-catch包装最常见的Exception捕获方法并查看它是否捕获了任何内容......

此外,令我烦恼的是你得到NULL的回复......