Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ignore missing entities in doctrine

We're porting over an application to Symfony2 and are currently stuck using doctrine ORM. We have a bunch of bad foreign keys in the database and it's getting increasingly more difficult to do the relationship mappings with out running into an "Entity not found" exception. It's on the roadmap to clean up the database but it's not something we can tackle right now unfortunately. Is there any way I can make it just return null if it fails to look up the proper entity?

If I have the following relationship mapping:

    User:
      type: entity
      table: user
      id:
        userID:
          type: integer
          generator:
            strategy: NONE
      fields:
        contactName:
          type: string
          length: 255
          nullable: false
        contactPhone:
          type: string
          length: 255
          nullable: false
        companyName:
          type: string
          length: 255
          nullable: false
        username:
          type: string
          length: 255
          nullable: false
        password:
          type: string
          length: 255
          nullable: false
        email:
          type: string
          length: 255
          nullable: false
      manyToOne:
          address:
            targetEntity: Address
            joinColumn:
              name: addressID
              referencedColumnName: addressID
              nullable: true
              default: null



    -----------------------------------------------------

    Address:
      type: entity
      table: address
      id:
        addressID:
          type: integer
          generator:
            strategy: AUTO
      fields:
        street:
          type: string
          length: 255
          nullable: false
        street2:
          type: string
          length: 255
          nullable: false
        city:
          type: string
          length: 255
          nullable: false
        state:
          type: string
          length: 32
          nullable: false
        zip:
          type: string
          length: 10
          nullable: false
        country:
          type: string
          length: 40
          nullable: false

It seems that if there is a bad value for addressID in the user table i'll get an "Entity was not found." exception when sending it through the serializer.

like image 902
Matt Avatar asked Oct 25 '25 22:10

Matt


2 Answers

I just encountered this same issue and found this question when searching for a solution... which I didn't find. Here's what I did (using annotation):

  1. Make the relationship lazy:

    /**
     * @var Resource
     *
     * @ORM\JoinColumn(name="ResourceID", referencedColumnName="ResourceID")
     * @ORM\OneToOne(targetEntity="Resource", fetch="LAZY")
     */
     private $resource;
     private $_resource_is_valid = null;
    
  2. Modify the getter and always use it -- even internally in the class:

     /**
      * Returns the associated resource, accounting for bad references.
      * @return Resource|null
      */
     public function getResource()
     {
         if (is_null($this->_resource_is_valid))
         {
             try
             {
                 // We need to call a method that triggers a lazy load
                 if ($this->resource && $this->resource->getID())
                 {
                     $this->_resource_is_valid = true;
                 }
             }
             catch (\Doctrine\ORM\EntityNotFoundException $enf)
             {
                 $this->_resource_is_valid = false;
                 // consider creating a new resource object.
             }
         }
         if ($this->_resource_is_valid)
         {
             return $this->resource;
         }
         return null;
     }
    

This approach allows Doctrine to partially hydrate entities, and lets you trap the bad relationship in an area where you have more control.

like image 80
J.D. Pace Avatar answered Oct 28 '25 13:10

J.D. Pace


Ah, this is the PITA that we see quite often too. If you've got lazy loading disabled then Doctrine could be loading & hydrating all linked entities at the time. But I'm guessing its turned on and its dying when you try and render a template / form in Symfony.

With Lazy Loading on, you won't get the error when you load the entity, you will however get the error if you then try and access a property of the related entity (which will cause Doctrine to load it) or render the entity in a symfony form and a field on the form relates to a property of the foreign table.

Unfortunately there is no easy way to stop or catch this. My advice would be to manually check the data for bad foreign keys and clean up the data, Doctrine's lazy loading is particularly unforgiving of bad data and Symfony just makes this worse by blowing up with an Error 500 if it comes across a duff link.

like image 45
Steve Childs Avatar answered Oct 28 '25 12:10

Steve Childs



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!