hundrix
hundrix

Reputation: 36

Symfony3 : Relation One to Many return empty object

I am trying to get the content of the One to Many author attribute in my Strip entity. The relation is between the Account and the Strip entities, bidirectional, and possessed by the Strip entity.

Here is my code for both of them:

Strip.php

/**
* Strip
*
* @ORM\Table(name="strip")
* @ORM\Entity(repositoryClass="AppBundle\Repository\StripRepository")
*/
class Strip
{
//...
    /**
     *
     * @ORM\ManyToOne(targetEntity="Account", inversedBy="strips")
     * @ORM\JoinColumn(name="author_id", referencedColumnName="id")
     */
    private $author;
//...
}

Account.php

/**
 * Account
 *
 * @ORM\Table(name="account")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\AccountRepository")
 */
class Account
{
    //...
    /**
     * @var array
     *
     * @ORM\OneToMany(targetEntity="Strip", mappedBy="author")
     */
    private $strips;

    public function __construct() {
        $this->strips = new ArrayCollection();
    }
    //...
}

When I try to get the author attribute from a strip, I get an empty account with the right id, but empty on the other fields (username, slug, ...).

For example, here is what a dump($strip->getAuthor()) returns:

MyController.php on line 326:
Account {#773 ▼
  +__isInitialized__: false
  -id: 1
  -username: null
  -email: null
  -emailIsPublic: 0
  -password: null
  -avatar: null
  -biography: null
  -level: 1
  -registerDate: null
  -strips: null
  #slug: null
   …2
}

Here are screenshots of my database showing that this relation is correctly registered:

Database screenshot strip table: Database screenshot strip table

Database screenshot account table: Database screenshot account table

Upvotes: 2

Views: 1352

Answers (2)

hundrix
hundrix

Reputation: 36

How I solved this problem

I did a custom joined query in StripRepository.php to get both of the Account and Strip entities content:

StripRepository.php

class StripRepository extends \Doctrine\ORM\EntityRepository
{

    public function findAuthors($strip)
    {
        $query = $this->getEntityManager()
                ->createQuery(
                        'SELECT s, a 
                        FROM AppBundle:Strip s
                        JOIN s.author a
                        WHERE s.id = :id'
                )
                ->setParameter('id', $strip);

        try
        {
            return $query->getSingleResult();
        }
        catch (\Doctrine\ORM\NoResultException $e)
        {
            return null;
        }
    }

}

What was the problem ?

Doctrine2 uses lazy loading by default and so doing that allows to load all the content from both entities, instead of just loading the content from Strip entity.

I read the Symfony documentation again about Doctrine associations where I found the example code I used:

Of course, if you know up front that you'll need to access both objects, you can [...] issue a join in the original query.

Joining Related Records - Symfony 3.4

Thanks to Mocrates who put me on the lead:

Or Better solution make a custom query in a StripRepository and select Author

Upvotes: 0

Mocrates
Mocrates

Reputation: 209

Doctrine2 use lazy loading.

Whenever you have a managed entity instance at hand, you can traverse and use any associations of that entity that are configured LAZY as if they were in-memory already. Doctrine will automatically load the associated objects on demand through the concept of lazy-loading

Hi it's a fetch lazy by Doctrine ... try to put in your :

/**
 * @var array
 *
 * @ORM\OneToMany(targetEntity="Strip", mappedBy="author", fetch="EAGER")
 */
private $strips;

Or Better solution make a custom query in a StripRepository and select Author

$this->createQueryBuilder('s')
     ->addSelect('a')
     ->join('s.author', 'a')

Upvotes: 5

Related Questions