Outils pour utilisateurs

Outils du site


pele_mele:stack_exchange:stackoverflow-27972741

Is there a better way to handle the Doctrine proxy object

I have two classes linked with a one-to-one relation.

class Client {
    ...
    /**
     * @ORM\OneToOne(targetEntity="ClientInfo")
     * @ORM\JoinColumn(name="id", referencedColumnName="client_id")
     */
    private $info;
    ...
    public function doSomething() {
        if (!$this->getInfo() instanceof ClientInfo) {
            return false;
        }
        return $this->getInfo()->doSomething();
    }
    ...
}
 
class ClientInfo {
    ...
    /**
     * @ORM\Id
     * @ORM\OneToOne(targetEntity="Client")
     * @ORM\JoinColumn(name="client_id", referencedColumnName="id")
     */
    private $client;
    ...
    public function doSomething() {
        return 'something';
    }
    ...
}

Those classes are loaded with database content with Doctrine. It is working perfectly when there is data in the database. But if there is not ClientInfo data, I have a \Doctrine\ORM\EntityNotFoundException raised.

So I changed the doSomething() method to take this into account.

    public function doSomething() {
        if (!$this->getInfo() instanceof ClientInfo) {
            return false;
        }
        try {
            return $this->getInfo()->doSomething();
        } catch (\Doctrine\ORM\EntityNotFoundException $e) {
            return false;
        }
    }

But it does not feel right to me since it is tied with Doctrine. I am trying to modify my unit tests to add a mock of the proxy object but it does not feel right either.

Is there a better way of doing that?

EDIT 1

I followed Nico Kaag suggestion but it does not change anything.

My constructor in my Client class look like this:

public function __construct() {
    $this->info = new ClientInfo();
}

If I do a var_dump of $this→info after retrieving my object with Doctrine, this is what I get.

object(Proxies\__CG__\MyBundle\Entity\ClientInfo)[444]
  public '__initializer__' => 
    object(Closure)[461]
  public '__cloner__' => 
    object(Closure)[462]
  public '__isInitialized__' => boolean false
  private 'client' (MyBundle\Entity\ClientInfo) => string '21055' (length=5)
  ...

EDIT 2

I finally changed what I have done. I removed the try..catch block and change the query to retrieve objects from database. Now I force the query to retrieve the ClientInfo object at the same time as the Client object.

This way, I can trust my test and if I forget to query both objects simultaneously, I will have an exception to remind it to me.

See I have made classes for you.

use Doctrine\ORM\Mapping AS ORM;
 
/**
 * @ORM\Entity
 */
class client
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
 
    /**
     * @ORM\OneToOne(targetEntity="Entities\client_info", inversedBy="client")
     * @ORM\JoinColumn(name="client_info_id", referencedColumnName="id", unique=true)
     */
    private $clientInfo;
}
use Doctrine\ORM\Mapping AS ORM;
 
/**
 * @ORM\Entity
 */
class client_info
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
 
    /**
     * @ORM\OneToOne(targetEntity="Entities\client", mappedBy="clientInfo")
     */
    private $client;
}

Try this, you will not get such issue.

Also I have used bi-directional relation with cardinality one-to-one, parent connection 0:1*- (parent optional), please see the diagram.

Suggetion : Use ORM designer tool for designing and extracting entity classes.

pele_mele/stack_exchange/stackoverflow-27972741.txt · Dernière modification : 2020/11/18 05:43 de alexis