phpsymfonyormdoctrinegetter

Why direct access of data fetched from db using doctrine does not work while using getter do work?


In PHP Symfony project with doctrine, I am using following class with self-referencing attribute "credit" and another attribute referencing class foo as follow.

/**
 * Bill
 *
 * @ORM\Table(name="bill")
 * @ORM\Entity(repositoryClass="BillRepository")
 */
class Bill {
    /**
     * @var Bill
     * @ORM\ManyToOne(targetEntity="Bill")
     * @ORM\JoinColumn(name="credit_id", nullable=true)
     */
    private $credit;
    public function getCredit() {return $this->credit;}

    /**
     * @var Foo
     * @ORM\ManyToOne(targetEntity="Foo")
     * @ORM\JoinColumn(name="foo_id", nullable=true)
     */
    private $foo;
    public function getFoo() { return $this->foo; }

    public function getCreditFooDirectAccess() { return $this->getCredit()->foo; }
    public function getCreditFooMethodAccess() { return $this->getCredit()->getFoo(); }
}

/**
 * Foo
 *
 * @ORM\Table(name="foo")
 * @ORM\Entity(repositoryClass="FooRepository")
 */
class Foo {
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    public function getId() { return $this->id; }
}

Now the two following controllers are showing different results. The direct access on displays NULL whereas the method access one displays some ID. Any ideas ? I am wondering if this is related to the way I am fetching the data.

public function testDirectAccessAction(Request $request)
{
    $dql = "SELECT bill FROM Bill bill";
    $bill = $this->getEm()->createQuery($sql)->getFirstResult();
    var_dump($bill->getCreditFooDirectAccess() ? $bill->getId() : null);
    die;
}
public function testMethodAccessAction(Request $request)
{
    $dql = "SELECT bill FROM Bill bill";
    $bill = $this->getEm()->createQuery($sql)->getFirstResult();
    var_dump($bill->getCreditFooMethodAccess() ? $bill->getId() : null);
    die;
}

Still working on isolating the problem some provided code is more like pseudo-code for now.

Thanks


Solution

  • This is normal behavior of doctrine lazy loading mechanism using proxy objects.

    Someone pointed out it was not clear in the docs here : https://github.com/doctrine/common/issues/934, which lead to a change in doctrine doc here : https://github.com/doctrine/orm/pull/9311.

    As now stated in the doc, given class A, it is dangerous to perform direct access of private attributes of any instance of class A other than $this.