Search code examples
doctrine-odm

How to suppress a MongoDDException when proxy can't find a referenced document


We are using Symfony2/DoctrineOdm/MongoDB and when we do:

if ($doc.referenceOne != null) { ... }

and the $doc.referenceOne contains a MongoDbRef that point to a deleted/lost document, the Doctrine Proxy object raises a MongoDBException.

It is possible to tell the Proxy return null instead of raising the exception?


Detailed Explanation:

Our document:

class User {
    /* @MongoDB\ReferenceOne( ... ) */
    private $photo;
}

If $photo contains a MongoDbRef, but the document is lost/deleted,

when we do if ($user.photo) { ... } doctrine will raise a MongoDBException:

The "Proxies\DocumentPhotoProxy" document with identifier "4fd8b3ef732bafab7b000000" could not be found

We want to suppress the exception since our application can handle null values in that variable.

(we could simply log that error, while the exception propagate to a 500 page and disrupt our service)


Solution

  • Edit 2: Doctrine extensions reference integrity can also help. It nullifies the invalid reference automatically. You can find more information on their GitHub repository: https://github.com/l3pp4rd/DoctrineExtensions/blob/master/doc/reference_integrity.md and for Symfony2 integration: https://github.com/stof/StofDoctrineExtensionsBundle

    Edit: I couldn't understand if you were referring to twig templates or php. Below you will find a solution for twig but if your question is about php adding a try...catch block for your getter might help you fix the problem.

    I don't know if you have already found a solution but in case if anyone else needs this I've used a (dirty) work around:

    Overwrite Twig_Template class by defining a custom one in your main configuration file (config.yml)

    Example:

    # app/config/config.yml
    base_template_class: Acme\DemoBundle\Template
    

    And overwrite the getAttribute method with a try...catch block:

    <?php
    
    namespace Acme\DemoBundle;
    
    use Doctrine\ODM\MongoDB\DocumentNotFoundException;
    
    abstract class Template extends \Twig_Template
    {
        protected function getAttribute($object, $item, array $arguments = array(), $type = \Twig_TemplateInterface::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
        {
            try {
                $ret = parent::getAttribute($object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck);
            } catch (DocumentNotFoundException $e) {
                $ret = null;
            }
            return $ret;
        }
    }
    

    This will ignore all DocumentNotFoundExceptions.

    Be careful though, invalid references are still there in your database. This only ignores the exception thrown in your twig templates.