1

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

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

例如,它需要可以评论 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();
    }

最后,这是我尝试从给定 StoryThread 实体中检索 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 方法工作或另一种可行的方法?谢谢

4

1 回答 1

1

我原以为我需要提供对象,因为“故事”列指的是故事实体,但事实证明我只需要使用 id 代替:

$thread = $repository->findOneBy(array(
    $repository->getObjectColumn() => $object->getId()
));
于 2012-05-15T14:19:39.780 回答