我正在构建一个CMS,它具有动态路由,版本控制系统和多种不同的内容类型,例如:文章,个人资料等我有一个ContentType实体,存储View可以使用的所有可用内容类型。但该内容类型实例的数据将存储在一个单独的实体中(因为这些字段对于每种类型的内容都是唯一的,因此它不能完全适合ViewVersion
)。
Routing --> View --> ViewVersion --> Article
or
Routing --> View --> ViewVersion --> Profile
Routing A --ManyToOne--> View D
Routing B --ManyToOne--> View D
Routing C --ManyToOne--> View D
View D --> ManyToOne -> ContentType (define what type this view is)
View D --> OneToOne --> Settings
View D --OneToMany--> ViewVersion E
View D --OneToMany--> ViewVersion F
View D --OneToMany--> ViewVersion G (*published version*)
ViewVersion E --OneToOne--> Article E
ViewVersion F --OneToOne--> Article F
ViewVersion G --OneToOne--> Article G
有关应用程序工作流程的详细背景信息(仍在不断变化),您可以在my related question here的“项目背景和代码结构”标题下看到描述。
这些内容类型中的每一个都将具有不同的字段和功能,因此它们将以唯一的捆绑包定义,并且它们需要存在于各自独立的实体(具有唯一字段的数据库表)中。
我的主控制器基于View
网址找到Routing
,并加载正确的捆绑控制器来组合页面(具有唯一的功能和身体区域的模板)。
Routing
实体存储一个或多个指向View
实体的网址。
View
实体是路由可以指向的基本占位符,然后指向多个版本,并设置已发布版本的ID。
ViewVersion
包含HTML页面,元数据,设计shell,浏览器标题等的所有基本信息,但不包含内容。新用户编辑时保存新ViewVersion
,或者30分钟内未保存该版本。
没有ContentType实体,它将是捆绑包中的实际实体,例如Gutensite\ArticleBundle\Entity\Article
,Gutensite\ProfileBundle\Entity\Profile
等将基于View-> ContentType集直接链接到ViewVersion(因此我们知道它是什么类型的实体)。 ContentType(例如Article)将OneToOne返回到ViewVersion的相应id,例如, Article-> viewVersionId(每个版本都有一个内容类型记录)。每次保存新的ViewVersion时,也会保存相应的ContentType(克隆所有实体关联)。它们本质上是一条记录,由于视图和多种内容类型之间的动态关系,它们被分成不同的实体。
传统的ORM映射在ViewVersion和动态ContentType之间不起作用,因为内容可能是不同包中的几个不同实体之一,因此我无法映射到单个静态文章或配置文件实体。这种联系需要是动态的。
我想设置关联,以便我可以轻松调用$ viewVersion-> getContent()来获取内容类型字段,还可以使用formBuilder为该实体加载正确的formType。
很容易为表单构建器关联正确的FormType:
class ViewVersionType extends AbstractType
{
public function getName()
{
return 'viewVersion';
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Add all the regular Fields
$builder->add(...);
// Add Dynamic Content Type Association
//Get the form type for the requested content type and merge with the default view form
$viewVersion = $builder->getData();
$view = $viewVersion->getEntity();
$contentPath = $view->namespace_bundle.'\\Form\\Type\\'.$view->getContentType()->getBundle().'Type';
$builder->add('content', new $contentPath, array(
'label' => false
));
}
}
但是,在ViewVersion和相关的ContentType之间添加动态映射的最佳方法是什么?
我读到了Resolve Target Entities,但这似乎不是最好的选择,而且你必须在orm配置中注册每个不理想的捆绑包。
我还阅读了Dynamic Form Modification,但鉴于我的表格解决方案并没有解决实体映射的基本问题,这并不是必需的。
我还读到了dynamic mapping via an event subscriber这似乎正是我所需要的。我假设我将特征放在动态内容类型实体上,指向BACK到ViewVersion。然后我会看到两者之间的映射关联。但我仍然无法弄清楚如何在该订阅者事件中访问我需要的数据,以正确告诉ViewVersion有关Article或Profile实体的信息。我还没有掌握Symonfy架构的全貌,知道一切是如何相关的,如何访问我需要的变量,以及在哪里找到合适的文档!
答案 0 :(得分:2)
这里的一些想法可能会有所帮助(或不):
您尝试实现的结构类似于Drupal使用节点,内容类型和节点修订来管理内容的方式。您可能希望详细了解它们如何构建here。
我觉得ContentType
应与View
而不是ViewVersion
相关联。我无法想象同一视图的不同版本可以具有不同的内容类型。视图应具有特定类型和不同版本。
我无法理解为什么View -> ContentType
将成为OneToOne关系。我会说有一组内容类型,每个View
都分配给一个ContentType
,所以它看起来更像是一个ManyToOne关系。
我不会尝试为每种内容类型制作一个包。我会说你可以拥有一个包含不同内容类型和视图的Blog
包。
View
实体可以$content_type_id
引用ContentType
的ID。 Doctrine使用lazy loading,当您加载View
实体时,doctrine将不关心它链接到的ContentType
,但会知道View
的content_type_id以及何时您需要链接的ContentType
,它会运行查询以获取它并将正确的ContentType
链接到您的View
。
我总是通过查看symfony bundles的源代码来了解最新动态,并了解事情的结构。