1
votes

I think this is possibly a similar issue to this question but I'm not able to comment yet and didn't want to bump it by providing a non-answer answer.

I'm making a commenting Symfony2 bundle that allows me to directly relate comments to various different entity types, so I've created an abstract comment 'thread' entity, which is then extended by a concrete thread entity per object type that can receive comments.

So for example it needs to be possible to comment on the Story entity, so I've created a concrete StoryThread entity that extends Thread and specifies a OneToOne attribute that links to the Story. The idea being that I can then do $storyThread->findOneBy('story', $story)->getComments();. However, findOneBy always returns null. When I run the raw SQL that I retrieved from debugging into it and fill in the relevant story_id, I do get back the expected result.

Here is the abstract thread entity:

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();
    }

and here is the concrete StoryThread entity:

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();
    }

And finally here is how I'm trying to retrieve the StoryThread object from a given Story entity: (getThreadEntityName gets the fully qualified StoryThread class name, and getObjectColumn returns the name of the column used to map an ObjectThread entity to it's object, so in this case "story")

/**
 * @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;
}

Here is the SQL that is generated within the findOneBy method: (when I replace ? with an actual story id, such as 1, I get back a single result as I'd expect)

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 = ?

Could anyone tell me how I can either get the findOneBy method to work or perhaps an alternative way that would work? Thanks

1
did you try $storyThread->findOneBystory($story)->getComments(); ??Philemon philip Kunjumon
Sorry for the delay, I didn't get a chance to try that until now. This produced the same result. However my extra day of wisdom since posting this yesterday led me to try using $object->getId() as the value, and that seems to have done the trick! :)RobMasters

1 Answers

1
votes

I would have thought I'd need to provide the object seeing as the 'story' column refers to a story entity, but it turns out I just needed to use the id instead:

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