3

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.

Fra Ore
  • 59
  • 2
  • 6
  • Post your entity classes with the annotations, or the config files! – delboy1978uk Sep 12 '17 at 10:52
  • Have you tried to clear the cache? You posted to few informations for us to be able to help with anything. – Mike Doe Sep 12 '17 at 10:55
  • Yes mike, i tried to cache clear, restart httpd, restart mysqld, restart server, run composer update, run php bin/console doctrine:schema:update --force – Fra Ore Sep 12 '17 at 10:56
  • can add your related entity – Robert Sep 12 '17 at 10:57
  • Can you post your query and your entity classes. You might be stumbling against lazy loading. The best guess with the few info given would be to change your request add a join and a select. – Sylvain Martin Saint Léon Sep 12 '17 at 11:35
  • Sorry guys I found the solution here: https://stackoverflow.com/questions/27489811/doctrine-many-to-one-returns-only-the-identifier I must add fetch="EAGER" on $worker property of Document Entity... I don't understand why, but it works! – Fra Ore Sep 12 '17 at 11:53
  • I must insist. In your use case it is not necessary to use fetch="EAGER". Doctrine will fetch the associated entity without anything else to your classes you just need to ask for the needed property using a getter of your class : see my answer below. Using fetch="EAGER" will drastically lower you performances in a large list... – Sylvain Martin Saint Léon Sep 12 '17 at 14:31
  • post please your solution by yourself and mark it as solved – Vasilii Suricov Dec 25 '18 at 09:17
  • if it really works... – Vasilii Suricov Dec 25 '18 at 09:18

1 Answers1

1

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.