【问题标题】:Doctrine ODM returns proxy object for base class instead of sub-classed documentDoctrine ODM 返回基类的代理对象而不是子类文档
【发布时间】:2013-02-26 03:52:52
【问题描述】:

在为我的项目提供新功能的工作期间,我决定扩展模型。我决定使用基类,对常用方法进行分组,只有很少的子类,都保存在一个集合中。

基础,抽象类:

/**
* @MongoDB\Document(repositoryClass="EntryRepository")
* @MongoDB\MappedSuperclass
* @MongoDB\InheritanceType("SINGLE_COLLECTION")
* @MongoDB\DiscriminatorField(fieldName="type")
* @MongoDB\DiscriminatorMap({"entry"="Application_Model_Entry", "image"="Application_Model_Image", "movie"="Application_Model_Movie"})
*/
abstract class Application_Model_Entry
{
    abstract function foo();
}

一些具体的类(我还有几个,类似,但有些是抽象的):

<?php
/** @MongoDB\Document */
class Application_Model_Image extends Application_Model_Entry
{
    function foo()
    {
        return 'foo';
    }
}

在那次转换之后,我打开了我的索引页面,并出现了一个错误 - PHP 试图调用一个抽象方法,因为 Doctrine 返回的对象是 base 类的代理。我以为这是因为我将集合从 Application_Model_Image 重命名为 Application_Model_Entry 并且内部对象引用(DBRef$ref 字段)仍然指向 Application_Model_Image,但我注意到一些有趣的事情:always 第一个查询结果是一个具体类的正确文档,其余的是基类代理 - 在我从数据库中删除第一个对象后,第二个就正常了。

在一个显示单个对象的页面上,所有对象都可以正常工作,所以我认为这可能是 Zend Framework 的寻呼机类迭代结果的原因,所以我跳过了寻呼机并直接从查询中转储了对象。我打印了 100 个第一个结果的类,其中一些具有适当的类 (Snippet of that list on pastebin)。我查看了数据库,但我发现数据没有什么特别之处(working vs not working)。我认为引用可能有问题,但正如我在上面所写的,如果同一个对象位于结果列表的第一个位置,它可能会起作用。

有什么想法或提示吗?我可以调试更多,但我需要被告知在哪里查看 Doctrine 的代码。

【问题讨论】:

  • Document 注释不应与MappedSuperclass 一起使用。前者用于具体实现,后者用于抽象类。除了第一个是代理对象之外,我不了解查询结果,因为代理只能在 ReferenceOne/Many 关系的上下文中创建为占位符。
  • 查询结果就像我在第一个 pastebin 链接中显示的一样 - 第一个是具体类,其余大部分是代理(具体为 ProjectProxy__CG__\Application_Model_Entry)。删除Document 注释后,一切似乎都正常,非常感谢。目前不是这样,但如果我愿意,我还能为整个继承树指明集合名称吗?
  • 我不相信MappedSuperclass 支持任何选项,因此您必须进行试验。根据单集合继承映射,所有继承类仍应存储在同一个集合中,但名称本身可能最终派生自抽象类的名称。
  • 很遗憾你是对的。在重构之前,我有一个自定义存储库类,我希望仍然能够使用它,但由于MappedSuperclass 不接受任何参数,所以这是不可能的。我看到您提出了一项可以允许继承的更改,但后来您放弃了。我的理由是,虽然我可以为所有最终类指定存储库类,但我无法获得代表整个继承树的存储库对象(调用 getRepository 时我必须提供一个类,并且我不能使用基类) ,只有定义了 repoclass 的具体类。

标签: php mongodb doctrine doctrine-odm odm


【解决方案1】:

根据上面 jmikola 的评论,我删除了 Document 注释,一切都开始顺利进行。奇怪的结果导致我在错误的地方寻找错误,但幸运的是我在这里得到了提示。

为了后代:

  • Document 注解用于具体类
  • MappedSuperclass 注解用于抽象类
  • 如果您在查询结果中收到代理类对象,则可能是您在该部门有混淆
  • 即使没有Document 注释,您也可以指示鉴别器字段/值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-23
    • 1970-01-01
    • 2014-03-20
    • 2014-11-12
    • 2013-10-14
    • 2014-06-12
    • 2017-10-06
    • 2017-12-25
    相关资源
    最近更新 更多