Search code examples
phpmongodbsymfonydoctrine-ormdoctrine-odm

Why is my PersistentCollection empty?


I'm using the Symfony 3 Framework with Doctrine and MongoDB.

I've two documents that are in an OneToMany relationship.

/**
 * Class Waypoint
 * @package AppBundle\Document
 * @MongoDB\Document(collection="waypoints", repositoryClass="AppBundle\Repository\WaypointRepository")
 */
class Waypoint
{
    /**
     * @var int
     *
     * @MongoDB\Id(strategy="auto")
     */
    private $id;

    /**
     * @var ArrayCollection
     * @MongoDB\ReferenceMany(targetDocument="Comment", cascade={"delete"})
     */
    private $comments;

}

**
 * Class Comment
 * @package AppBundle\Document
 * @MongoDB\Document(collection="comments", repositoryClass="AppBundle\Repository\CommentRepository")
 */
class Comment
{

    /**
     * @var int
     *
     * @MongoDB\Id(strategy="auto")
     */
    private $id;

    /**
     * @var Waypoint
     *
     * @MongoDB\ReferenceOne(targetDocument="Waypoint", inversedBy="comments")
     * @Assert\NotBlank()
     */
    private $waypoint;
}

Now I'm getting a part of my Waypoint entries from an repository query and want to display them with twig.

/**
 * WaypointRepository
 *
 * This class was generated by the Doctrine ORM. Add your own custom
 * repository methods below.
 */
class WaypointRepository extends DocumentRepository
{
    public function getWaypointsForCruiseByPage(Cruise $cruise, $page)
    {
        $displayLimit = 10;
        $amountToSkip = 0;

        if ($page > 1)
        {
            $amountToSkip = ($page -1) * $displayLimit;
        }

        $qb = $this->createQueryBuilder()
            ->select()
            ->field('cruise')->equals($cruise)
            ->field('isAutoWaypoint')->equals(false)
            ->sort('date', -1)
            ->skip($amountToSkip)
            ->limit($displayLimit)
        ;

        $qb
            ->addOr($qb->expr()->field('hasImage')->equals(true))
            ->addOr($qb->expr()->field('hasAudio')->equals(true))
            ->addOr($qb->expr()->field('description')->notEqual(''))
        ;

        return $qb->getQuery()->toArray();
    }
}

Now, I'm trying to do {{ waypoint.comments.count }} or {{ waypoint.comments|length }} will always be 0, even if I'm having datasets in my MongoDB collection.

If I'm getting the comments over the CommentRepository by the ID of the Waypoint I'm getting the expected results.

// returns the expected results
public function getAllCommentsForWaypoint(Waypoint $waypoint)
{
    return $this->createQueryBuilder()
        ->select()
        ->field('waypoint')->equals($waypoint)
        ->getQuery()->toArray()
    ;
}

The mapping is fine as far as I can tell, no flaws or errors to find.

Why is the PersistentCollection empty, event though informations are there in the collection?


Solution

  • I'm not sure how are you creating documents, but this is my best shot:

    Waypoint::$comments is not mapped as an inverse side thus ODM expects list of references to be available in the waypoint.comments field in the database. Most probably it's not there (i.e. you're not explicitly adding new Comment to the collection in the Waypoint) and that's why you're seeing empty collection when querying for waypoints, but have results when querying for comments. Given you have inversedBy="comments" in the Comment mapping I think you forgot to set the Waypoint::$comments as the inverse side:

    /**
     * @var ArrayCollection
     * @MongoDB\ReferenceMany(targetDocument="Comment", mappedBy="waypoint")
     */
    private $comments;