Doctrine related entities return all fields values NULL

3.6k views Asked by At

I am using Symfony 3.1.10 on a server with PHP 5.6.31 (with Zend OPcache 7.0.6-dev), Apache and MySQL (Ver 14.14 Distrib 5.6.37).

I have an Entity called Document with a related Entity called Worker

The relationship have always worked untill today... Non when I retrive a document with a worker, all the worker field are null (except the ID).

So if in my DB there is a worker with fields: id 4, name: John, age: 33 if I retrive a document with this worker relater and dump $document->getWorker() i return an objet Worker with id: 4, name: null, age: null.

The Document class

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(name="documents")
* @ORM\Entity(repositoryClass="AppBundle\Repository\DocumentRepository")
*/
class Document
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $object;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Worker", cascade={"persist"}, inversedBy="documents")
     * @ORM\JoinColumn(name="worker_id", referencedColumnName="id", onDelete="SET NULL")
     */
    protected $worker;

    public function getId()
    {
        return $this->id;
    }

    public function setObject($object)
    {
        $this->object = $object;

        return $this;
    }

    public function getObject()
    {
        return $this->object;
    }

    public function setWorker(\AppBundle\Entity\Worker $worker = null)
    {
        $this->worker = $worker;

        return $this;
    }

    public function getWorker()
    {
        return $this->worker;
    }
}

The worker class

namespace AppBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints AS Assert;

/**
* @ORM\Entity
* @ORM\Table(name="workers")
* @ORM\Entity(repositoryClass="AppBundle\Repository\WorkerRepository")
*/
class Worker
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", nullable=true)
     * @Assert\NotBlank()
     */
    protected $firstName;

    /**
     * @ORM\Column(type="string", nullable=true)
     * @Assert\NotBlank()
     */
    protected $lastName;

    /**
     * @ORM\Column(type="string", nullable=true)
     * @Assert\NotBlank()
     */
    protected $age;

    /**
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Document", mappedBy="worker")
     */
    protected $documents;

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

    public function __toString() {
        return $this->firstName . ' ' . $this->lastName;
    }

    public function getId()
    {
        return $this->id;
    }

    public function setFirstName($firstName)
    {
        $this->firstName = $firstName;

        return $this;
    }

    public function getFirstName()
    {
        return $this->firstName;
    }

    public function setLastName($lastName)
    {
        $this->lastName = $lastName;

        return $this;
    }

    public function getLastName()
    {
        return $this->lastName;
    }

    public function setAge($age)
    {
        $this->age = $age;

        return $this;
    }

    public function getAge()
    {
        return $this->age;
    }

    public function addDocument(\AppBundle\Entity\Document $document)
    {
        $this->documents[] = $document;

        return $this;
    }

    public function removeDocument(\AppBundle\Entity\Document $document)
    {
        $this->documents->removeElement($document);
    }

    public function getDocuments()
    {
        return $this->documents;
    }
}

I read here: Doctrine always return null values in production

I tried everything, but nothing works.

1

There are 1 answers

2
Sylvain Martin Saint Léon On

This really looks like a lazy loading problem : See, when you query for a document since your query doesn't explicitly ask for the worker, it is not loaded. The reference is loaded.

And here, you never call for worker this is why you get Worker {#701 ▼ +__isInitialized__: false

First have you tried calling $document->getWorker() outside of dump() ? dump won't fetch nested collection to avoid overwhelm memory. It should work in twig or even in a basic echo. echo $document->getWorker()->getFirstName()

When you get worker, use symfony debugger to see that you threw two queries, one to get the document and another one to get the worker. You should avoid this. This is called lazy loading. You never asked for worker but doctrine is a pretty fine ORM and it is smart enough to load it by itself.

It is not that problematic when you work with one entity, but think about the extra db work when you will be fetching a list of documents.

One better way to do this would be to use a custom query in the repository.