原则 2:有没有办法使用 yaml 或 xml 从特征继承映射?

问题描述 投票:0回答:2

我在学说文档中找到以下示例,他们在其中添加了对特征的映射:

/**
 * Trait class
 */
trait ExampleTrait
{
    /** @Id @Column(type="string") */
    private $id;

    /**
     * @Column(name="trait_foo", type="integer", length=100, nullable=true, unique=true)
     */
    protected $foo;

    /**
     * @OneToOne(targetEntity="Bar", cascade={"persist", "merge"})
     * @JoinColumn(name="example_trait_bar_id", referencedColumnName="id")
     */
    protected $bar;
}

我正在尝试映射一个特征,而不必在继承它的类中复制映射。我没有诚实地在上面尝试过这个,因为我当前的项目正在使用 yaml 进行映射,但它看起来像一个普通的 php 类在使用特征时也会继承映射。

有没有一种方法可以不使用关联而是使用 yaml 或 xml 来继承此特征的映射?我尝试将特征设置为 mapped superclass 但它没有用,但我基本上在寻找相同类型的想法。

谢谢。

php symfony doctrine-orm doctrine
2个回答
0
投票

我发现实现映射特征的唯一方法是使用订阅者。以下内容适用于您的示例,并且很容易定制:

<?php

namespace App\EventSubscriber\Doctrine;

use App\Model\Bar;
use App\Model\ExampleTrait;
use Doctrine\Common\EventSubscriber;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Events;
use Doctrine\ORM\Mapping\ClassMetadataInfo;

final class ResolveTraitSubscriber implements EventSubscriber
{
    public function getSubscribedEvents(): array
    {
        return [
            Events::loadClassMetadata,
        ];
    }

    public function loadClassMetadata(LoadClassMetadataEventArgs $args): void
    {
        $methods = [
            ExampleTrait::class => [$this, 'addExampleTrait'],
            // add more traits if needed...
        ];

        $metadata = $args->getClassMetadata();
        $traits = (array) $metadata->reflClass?->getTraits();

        foreach ($traits as $trait) {
            $name = $trait->getName();
            if (isset($methods[$name])) {
                $methods[$name]($metadata);
            }
        }
    }

    private function addExampleTrait(ClassMetadataInfo $metadata): void
    {
        $metadata->mapField([
            'fieldName' => 'id',
        ]);
        $metadata->mapField([
            'fieldName' => 'trait_foo',
            'length' => 100,
            'nullable' => true,
            'unique' => true,
        ]);
        $metadata->mapOneToOne([
            'targetEntity' => Bar::class,
            'cascade' => ['persist', 'merge'],
        ]);
    }
}

别忘了用

doctrine.event_subscriber
标签将它定义为服务。


-1
投票

使用 YAML 声明 mappedSupperClass:

Namespace\For\Your\MappingClass:
    type: mappedSuperclass
    fields:
        id:
            id:
                type: integer
                generator:
                    strategy: AUTO

        ... other fields and relations 

用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">

    <mapped-superclass name="Namespace\For\Your\MappingClass">

        <field name="foo" column="foo" type="string" length="255" />

        <field name="bar" column="bar" type="string" length="255" unique="true" />

        ... other fields

    </mapped-superclass>

</doctrine-mapping>

如果你运行

app/console doctrine:generate:entities
,你将能够在其他实体中使用 mappedSuperClass 作为方兴未艾。

© www.soinside.com 2019 - 2024. All rights reserved.