是否可以使用Doctrine';从懒惰加载的对象中获得实际类名而不是代理类名;的MongoDB ODM


Is it possible to get the actual class name instead of the proxy class name from a lazy loaded object using Doctrine's MongoDB ODM?

在开始将我的应用程序升级到Symfony 3,并将几个库(包括Doctrine)升级到最新版本之前,我能够将查询中的引用与早期查询的结果进行比较。我可以通过将早期查询结果中每个项目的派生类名(例如get_class($source))与新查询中数据库引用上的_doctrine_class_name字段进行匹配来实现这一点。这样可以正确地过滤掉类型不正确的文档。

由于升级了我的依赖项,当我获得源的派生类名时,我会得到一个代理,而不是实际的类名,例如MongoDBODMProxies''__CG__''AcmeBundle''Documents''MyClass而不是AcmeBundle'Documents'MyClass

在这种情况下,我试图筛选的对象集合是Activity对象,它们的属性中有一个$source属性,它是一个开放类型,也就是说,它没有显式的鉴别器映射,因为我希望它能够容纳任何文档。我试图重新开始工作的是一个查询,它使用ID和类名,通过匹配的源来过滤这些活动。查询代码如下:

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());
}

值得一提的是,我使用了以下版本的Doctrine和MongoDB ODM/捆绑包:

  • 条令/mongodb^1.3.0
  • 条令/mongodb odm^1.1.0
  • 条令/mongodb-odm捆绑包^3.2.0

查看ClassUtils类中的getClass(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"