1

Prior to beginning upgrade work to update my application to Symfony 3, and with it upgrading several libraries (including Doctrine) to more recent versions, I was able to compare references in a query to the results of an earlier query. I was able to do this by matching the derived class name (e.g. get_class($source)) of each item in the results of the earlier query to the _doctrine_class_name field on a database reference in the new query. This would properly filter out documents that were of the incorrect type.

Since upgrading my dependencies, when I get the derived class name of the source, I am getting back a proxy instead of the actual class name, e.g. MongoDBODMProxies\\__CG__\\AcmeBundle\\Documents\\MyClass instead of AcmeBundle\Documents\MyClass.

The collection of objects I am trying to filter in this case are Activity objects, among their properties is a $source property which is an open type, that is to say that there is no explicit discriminator map for it as I wanted it to potentially be able to hold any document. What I am trying to get working again is a query that filters these activities by their matching sources, using ID and class name. The query code looks like this:

public function findAllBySource($sources = array(), $date = null, $limit = 50)
{
    $qb = $this->createQueryBuilder()->limit($limit)->sort('date', 'DESC');

    if (!empty($date)) {
        $qb->field('date')->lte($date);
    }

    $qb->addOr($qb->expr()->field('source')->exists(false));
    foreach ($sources as $source) {
        // $source is initialized as a proxy to the real class here
        // using get_class($source) returns the class name to the
        // proxy, not the actual FQCN, e.g. AcmeBundle\Document\MyClass
        $expr = $qb->expr()
            ->field('source.$id')->equals(new \MongoId($source->getId()))
            ->field('source._doctrine_class_name')->equals(get_class($source));
        $qb->addOr($expr);
    }
    $query = $qb->getQuery();
    return array_values($query->execute()->toArray());
}

For what it is worth, I am using the following versions of the Doctrine and MongoDB ODM/bundles:

  • doctrine/mongodb ^1.3.0
  • doctrine/mongodb-odm ^1.1.0
  • doctrine/mongodb-odm-bundle ^3.2.0
2
  • Just to clarify, are you looking to get "MyClass" instead of "MongoDBODMProxies\__CG__\\...\\MyClass"? Commented Jul 20, 2016 at 3:41
  • Sorry, I should be have been more clear, yes and no: I want the FQCN sans the proxy prefix, so basically the actual FQCN of the class, so if the class was located in AcmeBundle\Documents\MyClass and the proxy class showed MongoDBODMProxies\\__CG__\\AcmeBundle\\Documents\\MyClass I would want the AcmeBundle\Documents\MyClass class name. I'll update to add that clarity. Commented Jul 20, 2016 at 3:59

1 Answer 1

3

Check out the getClass from ClassUtils class (part of Doctrine Common):

<?php

// $source is an instance of MongoDBODMProxies\\__CG__\\AcmeBundle\\Documents\\MyClass

$source = Doctrine\Common\Util\ClassUtils::getClass($source);

echo $source; // $source should now be "AcmeBundle\Documents\MyClass"
Sign up to request clarification or add additional context in comments.

2 Comments

That is awesome. It's odd though, getRealClass seemed to supply additional data at the end of the class name that looked like a positional marker (@XXXXX) and didn't work, but when I used getClass from the class utils everything worked. It might have just been an odd side effect. Still thank you very much for pointing me to that utility, I wasn't aware of it previously!
After reading the code of ClassUtils a bit more closely, it appears using getClass is correct. $source is an instance, not a string - my mistake. Glad I could be of help. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.