【发布时间】:2026-02-03 17:15:01
【问题描述】:
我有一个站点记录,其中可以包含任意数量的具有不同信息的 AdProvider 配置字段。不幸的是,fieldNames(提供者的名称)是独一无二的,而且还会有更多。我可以在 Document 中将它们中的每一个硬编码为哈希类型,但是每次添加新的 Provider 时我都必须更新 Document。
我想动态修改 Document 本身,查看可以从另一个 Mongo 集合中获取的 Providers 列表,但我不知道该怎么做。
我的第一次尝试是在 loadClassMetaData 事件上创建一个侦听器并映射新字段。我看到了字段映射,但它们没有反映在文档中。显然这些字段没有任何 getter 和 setter,所以我尝试使用神奇的 __get 和 __set 方法访问它们,但我得到它们不存在的错误。
也许我用错了方法?
Mongo 记录示例:
{
"_id" : ObjectId("4ff1d29d99c6667722000000"),
"_type" : [
"Models_Site"
],
"enabledAdProviders" : [
"provider1",
"provider2",
"provider3",
"provider4"
],
"provider1" : {
"id" : "4028cbff38e2d7c00666fd2fdc770208"
},
"provider2" : {
"placements" : {
"Top_300x50" : "477",
"Btm_300x50" : "478",
"Top_320x50" : "477",
"Btm_320x50" : "478"
}
},
"provider3" : {
"id" : "8a809449013331fdcdc6662708532b20"
},
"siteId" : "PsTl",
"siteName" : "Publisher Site",
"provider4" : {
"placements" : {
"Top_300x50" : "430",
"Btm_300x50" : "430"
}
}
}
我的听众:
<?php
namespace BIM\DataBundle\Listener;
use BIM\DataBundle\Document\AdPublisherRecord;
use BIM\DataBundle\Document\AdProviderRecord;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
class AdPublisherSiteSetup
{
private $serviceContainer;
/**
* This service is called every time Ads doctrine odm loads a document.
* We are dynamically creating the ad provider setting nodes on the AdPublisher Record
*
*/
public function __construct($serv){
$this->serviceContainer = $serv;
}
public function loadClassMetadata(\Doctrine\ODM\MongoDB\Event\LoadClassMetadataEventArgs $args)
{
$metaData = $args->getClassMetadata();
$document = (string)$metaData->getName();
if($document == "BIM\DataBundle\Document\AdPublisherRecord"){
//query for ad providers
//create as a hash type to store each providers settings.
$providerList = $this->serviceContainer->get('ads.publisher.factory')->getProviderList();
foreach ($providerList as $name => $value) {
$metaData->mapField(array('fieldName' => $name, 'type' => 'hash'));
}
}
}
}
【问题讨论】:
-
我不认为你想做的事情是可能的。 Doctrine 文档是“静态的”,因此您要加载的字段必须存在于文档中,否则将不会加载。如果你能解释一下你想要达到的目标,我想有更好的方法来做到这一点。
-
我希望我的应用程序能够与新输入的广告提供商一起工作(生成创建或编辑站点记录时所需的正确表单字段。
-
我又玩了一些,如果我在检索记录之前修改了 classMetadata,我就能让它工作。但是,我需要在 Document 中定义属性并使用魔术方法,所以这样做似乎没有优势。我想我只需要添加属性,生成 getter 和 setter 并在新的 AdProvider 添加到数据库时重新部署。
标签: symfony doctrine doctrine-odm odm