Php 动态创建条令(伪)实体?

Php 动态创建条令(伪)实体?,php,mysql,doctrine-orm,doctrine,Php,Mysql,Doctrine Orm,Doctrine,我的主管向我提出了一个“是否可以在条令中完成”类型的问题,虽然我可以用外部的“映射器”对象完成其中的一些任务,但我想知道是否有任何方法可以伪造ORM在条令中完成任务 本质上,我们感兴趣的是减少数据库混乱。我们有许多表,其中包含不同类别的不同属性或项目集,然后有一大堆链接表将它们与其他属性或项目集联系起来。比如说 我们有两个表格,如“材料”和“纸张类型”,它们描述了我们产品的各种材料和纸张选项。然后,我们将这些分类为“材料集合”和“文件族”。然后,在MaterialCollection/Mater

我的主管向我提出了一个“是否可以在条令中完成”类型的问题,虽然我可以用外部的“映射器”对象完成其中的一些任务,但我想知道是否有任何方法可以伪造ORM在条令中完成任务

本质上,我们感兴趣的是减少数据库混乱。我们有许多表,其中包含不同类别的不同属性或项目集,然后有一大堆链接表将它们与其他属性或项目集联系起来。比如说

我们有两个表格,如“材料”和“纸张类型”,它们描述了我们产品的各种材料和纸张选项。然后,我们将这些分类为“材料集合”和“文件族”。然后,在MaterialCollection/Materials和PaperFamilies/PaperType之间必须分别有一个一对多链接表。重复这些类型的关系几十次,你就会看到我们的数据库开始混乱起来

链接表本身不过是一系列条目,包括多条记录,其中PrimaryId来自父表(集合/族),而PrimaryId来自子表(材质/纸张类型),每个父表都是唯一的。例如,链接表可以命名为MaterialCollectionsMaterials和PaperFamilyPaperType

其想法是通过使用抽象的3表结构来摆脱这一系列链接表,如下所示:

列表(由唯一的ListId、ListName和TypeId组成) 类型(由唯一的TypeId、TypeName和EntityName组成) ListXref(由ListID和memberId组成,指向列表类型中指定实体的primaryId)

给定类型可以存在多个列表,但外部参照对是唯一的。不同类型也可以指向同一实体。(例如,可能定义了多种类型的材料清单)

“ListName”将等同于上面的父表名,并允许删除这些关系中的两个表。因此,“MaterialCollections”中的记录现在将改为TypeName“MaterialCollection”列表中的记录。原本在链接表中的记录(如MaterialCollectionsMaterials)现在将从ListXRef指向

如前所述,我已经获得了一个基本的映射器,使其能够用于相当基本的列表创建。但我想知道的是,是否有任何方法可以创建实体或行为类似于条令实体的东西,以在给定列表/列表类型和EntityName引用的表以及相应的MemberID之间建立抽象关系

换言之,如果我有一些方法可以产生一些具有条令实体大部分功能的东西,这些功能可以从服务管理器中检索,或者类似的东西,它们的行为(具有类似的属性/功能)类似于条令实体,那就太好了

我尝试在实体树中添加一个包装器对象,映射者可以尝试检索该对象,该对象基本上是外部参照实体的继承版本,带有一些别名函数,但无法使用实体管理器检索

感谢您的帮助


顺便说一句,虽然目前这不是一个优先事项,但从长远来看,我还想通过尝试让一些列表能够指向其他列表生成的记录,来真正推动工作。因此,例如,“ProductMaterials”类型的“ProductXMaterials”列表可能会指向“MaterialCollections”的部分但不是全部结果。但我稍后会担心这个问题。

好吧,条令不能生成“伪实体类”,但您可以

首先,您需要连接到“loadClassMetadata”事件。 在内部,您可以动态地从代码生成实体类和配置,并将它们转储到指定的目录中(例如缓存中),以维护原则命名约定,但使用自定义名称空间。例如:“AutoGeneratedNamespace\Entities”

假设您需要为名为“TmpUser”的实体生成一个动态实体,并且您使用的是“yml”而不是注释

<?php
namespace Example;

use Doctrine\ORM\Event\LoadClassMetadataEventArgs;

class DoctrineEventListener
{
    /**
     * Invoked on Doctrine loadClassMetadata event
     *
     * @var Doctrine\ORM\Event\LoadClassMetadataEventArgs
     **/
    public function loadClassMetadata(LoadClassMetadataEventArgs $args)
    {
        $em             = $args->getEntityManager();
        $metadata       = $args->getClassMetadata();
        $factory        = $em->getMetadataFactory();
        $name           = 'AutoGeneratedNamespace\Entities\TmpUser';
        $tmpDirectory   = '/path/to/cache/generated-classes';

        // current class metadata is the same as the one we need. this means we already generated it
        if($metadata->getName() == $name || $factory->hasClassMetadata($name)) {
            return;
        }
        /** 
         Generate your class here and dump it into the cache directory with the name: TmpUser.php
         (If you're using "yml" instead of annotations also create the TmpUser.orm.yml configuration and dump it in the same directory)
        **/

        // create a metadata for the newly created class
        $metadata = $factory->newClassMetadataInstance($name);

        // Register metadata so doctrine knows about it
        $factory->setMetadataFor($name, $metadata);
    }

}
doctrine:
    orm:
        mappings:
            MyGeneratedEntitiesUniqueMappingsKey:
                type: yml
                dir: '/path/to/cache/generated-classes'
                is_bundle: false
                prefix: "AutoGeneratedNamespace\Entities"
                alias: GeneratedEntities