Доктрина 2: Как динамически разрешить «targetEntity» и JoinTable «name» в черте? - PullRequest
0 голосов
/ 24 апреля 2018

Я хочу создать Entity, который будет реализовывать следующий интерфейс.

<?php

namespace App\Entity\Interfaces;
#...

interface FooInterface
{
    /**
     * @param ArrayCollection|FooInterface[] $foo
     */
    public function setFoo($foo);

    /**
     * @return ArrayCollection|FooInterface[]
     */
    public function getFoo();
}

Для простоты я хочу использовать trait для наследования свойств и методов от него. Итак, наконец, мои сущности могут выглядеть примерно так:

<?php

namespace App\Entity\Entity;
#...

class Bar implements FooInterface
{
    use FooTrait;
}

и

<?php

namespace App\Entity\Entity;
#...

class Baz implements FooInterface
{
    use FooTrait;
}

Но я не знаю, как разрешить targetEntity и name динамически в аннотации @ORM.

<?php

namespace App\Entity\Traits;
#...

trait FooTrait
{
    /**
     * Many Foo has Many Foo.
     *
     * @ORM\ManyToMany(targetEntity="...")
     * @ORM\JoinTable(
     *     name="..."
     *     joinColumns={@ORM\JoinColumn(name="foo_id", referencedColumnName="id")},
     *     inverseJoinColumns={@ORM\JoinColumn(name="foo_of_id", referencedColumnName="id")}
     * )
     * @ORM\OrderBy({"id" = "ASC"})
     *
     * @var FooInterface[]|ArrayCollection
     */
    protected $foo;

    #...
}

Подход, который я выбрал, хороший? Если да, то как мне решить мою проблему?

1 Ответ

0 голосов
/ 24 апреля 2018

Я делал это раньше, это довольно забавно и немного сложно, но дает вашему приложению массу гибкости. То, что вы пытаетесь сделать, называется динамическим сопоставлением отношений.

Подробное руководство - здесь . Я рекомендую вам взглянуть на это. Я просто возобновлю шаги здесь:

  1. Сначала вам нужно очистить поля ORM Аннотации отношений, которые вы хотите динамически отобразить. Вы не можете сделать это с аннотациями.

  2. Во-вторых, вам нужно создать подписчика / прослушивателя событий, прослушивающего событие onLoadClassMetadata. Точное имя я не помню, но оно является константой в классе событий Доктрины.

  3. Тогда вам нужно слушать только сущности, которые реализуют желаемый интерфейс. Вы получите экземпляр ClassMetadadataInfo для события, который содержит ReflectionClass вашей сущности в памяти и кучу полезных методов для проверки, реализует ли данный интерфейс данный интерфейс или нет, и т. Д.

  4. В зависимости от ваших потребностей, вы должны вызывать либо mapManyToMany, mapManyToOne, mapOneToMany и т. Д., В классе метаданных. В качестве аргумента он принимает очень сложный и четко определенный массив, который содержит почти ту же информацию, которую вы поместите в аннотацию. Вы можете оставить большинство из них пустыми, чтобы использовать значение по умолчанию. Требуется предоставить информацию о классе и имя поля.

  5. Сохраните его, зарегистрируйте слушателя как службу и наслаждайтесь.

СТОРОННОЕ ПРИМЕЧАНИЕ: это не дорогая операция, потому что classMetadata кэшируется доктриной.

...