学说动态映射

时间:2016-12-06 14:15:37

标签: php database symfony doctrine

我尝试提高自己的CMS系统的灵活性。插件可以扩展此CMS系统的功能。这个“核心”CMS系统有几个实例。目前无法停用这样的插件,因此每个实例都激活了所有插件,尽管不是每个实例都使用每个插件。不幸的是,新创建的插件可能会破坏CMS的某种基本功能。我的目标是使插件结构更加灵活。一个任务是仅激活将由实例使用的插件。我的问题是,doctrine映射由XML Files处理,其中每个Table都定义了每个关系。

例如: 假设我们有基类File,它将是一个“核心”功能。有一天,我们添加了一个标记插件,我们将标签添加到文件中。例如,我们上传了一张“莱昂内尔·梅西”图片,并给它贴上标签:“Primera Division,soccer,argentinia,......”。可能的XML映射可能如下所示:

<?xml version="1.0" encoding="utf-8"?>
   <doctrine-mapping
       xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Db\File" table="file">
    <!-- identical for all tables -->
    <unique-constraints>
        <unique-constraint columns="id"/>
    </unique-constraints>
    <id name="uid" type="integer" column="uid">
        <generator strategy="AUTO"/>
    </id>
    <field name="id" type="integer" column="id" nullable="true"/>
    <field name="title" type="string" column="title" length="255" nullable="true"/>

    <one-to-many field="fileTags" target-entity="Tag" mapped-by="file">
    </one-to-many>
</entity>
</doctrine-mapping>

“文件”表与“标签”具有一对多的关系。虽然“tag”插件可能未被激活,但将为每个CMS实例创建此关系。只有在“tag”插件处于活动状态时才能创建与“tags”的关系,否则不应执行特定于插件的映射。

教条如何处理这样一项任务的最佳方式是什么?谢谢你的帮助!

1 个答案:

答案 0 :(得分:0)

您可以使用动态映射。

尝试使用doctrine loadClassMetadata事件向要添加标记的实体添加其他映射。以及您的标签实体本身。

    $mapping['fieldName'] = 'tag';
    $mapping['targetEntity'] = '<your entity>';
    $mapping['sourceEntity'] = '<your tag class>';
    $mapping['sourceToTargetKeyColumns'] = array('tag_id' => 'id');
    $mapping['targetToSourceKeyColumns'] = array('id' => 'tag_id');
    $mapping['fetch'] = 2;
    $mapping['joinColumns'] = array(
        array(
            'name' => 'tag_id',
            'unique' => false,
            'nullable' => false,
            'onDelete' => null,
            'columnDefinition' => null,
            'referencedColumnName' => 'id',
        )
    );
    $mapping['mappedBy'] = 'tag_id';
    $mapping['inversedBy'] = null;
    $mapping['orphanRemoval'] = false;
    $mapping['isOwningSide'] = true;
    $mapping['type'] = ClassMetadataInfo::MANY_TO_ONE;

    $vm = $this->em->getClassMetadata('<your tag class>');

    $vm->associationMappings["tagId"] = $mapping;

这没有经过测试,几乎肯定有点不对,但它可能会给你一些想法让你开始。

您可以使用XML来创建所需的映射。然后使用调试器检查生成的元数据。然后使用事件侦听器动态添加该元数据。最后删除XML映射并重新测试。

如果要引用标签中的实体和实体中的标签,您可能需要检查标签和目标实体上的映射