Doctrine2 findOneBy方法使用JOINED继承映射返回null

时间:2012-05-14 10:23:57

标签: php inheritance symfony doctrine-orm

我认为这可能与this question有类似的问题,但我无法发表评论,也不想通过提供非答案答案来解决这个问题。

我正在评论Symfony2包,它允许我直接将注释与各种不同的实体类型相关联,所以我创建了一个抽象注释'thread'实体,然后由每个对象类型的具体线程实体扩展可以收到评论。

因此,例如,它需要可以对Story实体进行评论,因此我创建了一个具体的StoryThread实体,该实体扩展了Thread并指定了链接到Story的OneToOne属性。这个想法是我可以做$storyThread->findOneBy('story', $story)->getComments();。但是,findOneBy始终返回null。当我运行从调试中检索到的原始SQL并填入相关的story_id时,我确实得到了预期的结果。

这是抽象线程实体:

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity(repositoryClass="Joe\Bundle\CommentBundle\Repository\ThreadRepository")
 * @ORM\Table(name="comment_threads")
 * @ORM\MappedSuperClass
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="thread_type", type="string")
 * @ORM\DiscriminatorMap( {"story" = "Joe\Bundle\StoryBundle\Entity\StoryThread"} )
 */
abstract class Thread
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="boolean")
     */
    protected $enabled = true;

    /**
     * @var datetime $createdAt
     *
     * @Gedmo\Timestampable(on="create")
     * @ORM\Column(name="created_at", type="datetime")
     */
    protected $createdAt;

    /**
     * @ORM\OneToMany(targetEntity="Comment", mappedBy="thread_id", cascade={"persist"})
     * @param ArrayCollection $data
     */
    protected $comments;


    function __construct()
    {
        $this->comments = new ArrayCollection();
    }

这是具体的StoryThread实体:

use Doctrine\ORM\Mapping as ORM;
use Joe\Bundle\CommentBundle\Entity\Thread as AbstractThread;

/**
 * @ORM\Entity(repositoryClass="Joe\Bundle\StoryBundle\Repository\StoryThreadRepository")
 * @ORM\Table(name="story_comment_threads")
 */
class StoryThread extends AbstractThread
{
    /**
     * @ORM\OneToOne(targetEntity="Story")
     * @ORM\JoinColumn(name="story_id", referencedColumnName="id")
     */
    protected $story;

    /**
     * @var datetime $createdAt
     */
    protected $createdAt;


    public function __construct()
    {
        $this->comments = new \Doctrine\Common\Collections\ArrayCollection();
    }

最后,我将尝试从给定的Story实体中检索StoryThread对象:(getThreadEntityName获取完全限定的StoryThread类名,getObjectColumn返回用于将ObjectThread实体映射到其对象的列的名称,所以在这种情况下“故事”)

/**
 * @param CommentableInterface $object
 * @return AbstractThread
 */
public function findThreadByObject(CommentableInterface $object)
{
    /** @var $repository ThreadRepository */
    $repository = $this->em->getRepository($object->getThreadEntityName());

    $thread = $repository->findOneBy(array(
        $repository->getObjectColumn() => $object
    ));

    if (!$thread) {
        $thread = $this->createThread($object);
    }

    return $thread;
}

这是在findOneBy方法中生成的SQL :(当我用实际的故事ID替换?,例如1时,我会得到一个我期望的结果)

SELECT t1.id AS id2, t1.enabled AS enabled3, t1.created_at AS created_at4, t0.story_id AS story_id5, t1.thread_type FROM story_comment_threads t0 INNER JOIN comment_threads t1 ON t0.id = t1.id WHERE t0.story_id = ?

有人能告诉我如何让findOneBy方法工作或者可能采用另一种方法吗?感谢

1 个答案:

答案 0 :(得分:1)

我原本以为我需要提供对象,因为'故事'列指的是一个故事实体,但事实证明我只需要使用id:

$thread = $repository->findOneBy(array(
    $repository->getObjectColumn() => $object->getId()
));