Определение Discriminator Maps на уровне сущностей-потомков
Быстрый старт
Подключить обработчик событий Doctrine2:
use Nnx\Doctrine\DiscriminatorEntry\DiscriminatorEntryListener;
return [
'doctrine' => [
'eventmanager' => [
'orm_default' => [
'subscribers' => [
DiscriminatorEntryListener::class,
],
],
],
В корневой сущности обязательно нужно указать DiscriminatorMap, хотя бы с одним значением. Это связано с реализацией функционала по обработке DiscriminatorMap в Doctrine2. В качестве значения можно указать значение столбца дискриминатора для класса корневой сущности.
namespace Nnx\Doctrine\PhpUnit\TestData\DiscriminatorEntry\TestModule1\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Class RootEntity
*
* @ORM\Entity()
* @ORM\DiscriminatorMap()
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorMap(value={ "rootEntity" = "RootEntity" })
*/
class RootEntity
{
/**
* @var integer
*
* @ORM\Id()
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* @return int
*/
public function getId()
{
return $this->id;
}
}
В классе-потомке добавить анотацию Nnx\Doctrine\Annotation\DiscriminatorEntry:
namespace Nnx\Doctrine\PhpUnit\TestData\DiscriminatorEntry\TestModule1\Entity\Overload;
use Doctrine\ORM\Mapping as ORM;
use Nnx\Doctrine\Annotation as NNXD;
use Nnx\Doctrine\PhpUnit\TestData\DiscriminatorEntry\TestModule1\Entity\RootEntity as BaseEntity;
/**
* Class RootEntity
*
* @ORM\Entity()
* @NNXD\DiscriminatorEntry(value="overload")
*/
class RootEntity extends BaseEntity
{
// ...
}
В результате в DiscriminatorMap корневой сущности будет добавлена запись, ключом которой будет значение аннотации Nnx\Doctrine\Annotation\DiscriminatorEntry (в примере выше это "overload"), а значением — класс сущности потомка (в примере выше это Nnx\Doctrine\PhpUnit\TestData\DiscriminatorEntry\TestModule1\Entity\Overload\RootEntity)
Описание работы
Наследование сущностей в Doctrine2 реализуется с помощью специальной колонки (столбец дискриминатора), добавляемой к таблице, на которую отображается корневая сущность. Значение в этой колонке должно однозначно определять конечный класс сущности.
Для явного указания карты соответствий используется аннотация @DiscriminatorMap:
namespace MyProject\Model;
/**
* @Entity
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
*/
class Person
{
// ...
}
- @DiscriminatorMap определяет, какие значения столбца дискриминатора каким классам соответствуют. Например, значение "person" говорит о том, что запись имеет тип Person, а "employee" соответствует типу Employee.
- Названия классов в карте дискриминатора можно полностью не указывать, если они принадлежат тому же пространству имен, что и класс, к которому эта карта будет применена.
В случае если DiscriminatorMap не указывается, в качестве значения столбца дискриминатора берется короткое имя класса. (например, для \Nnx\Doctrine\PhpUnit\TestData\DiscriminatorEntry\TestModule1\Entity\Overload\RootEntity будет rootentity).
Поэтому если мы явно не указываем отношение между значением колонки дискриминатора и конкретным классом, необходимо следить за тем, чтобы в цепочке классов-потомков короткие имена классов всегда были различны.
В случае если сущность-потомок находится в другом по отношению к корневой сущности модуле, мы сталкиваемся с ситуацией, когда в DiscriminatorMap корневой сущности нужно явно указать класс из другого модуля. Т.е. возникает жесткая связь между модулями.
Для того чтобы решить данную проблему, используется специальное расширение, позволяющие указывать значение колонки дискриминатора, в сущности-потомке.
Для использования данного расширения необходимо зарегистрировать его:
use Nnx\Doctrine\DiscriminatorEntry\DiscriminatorEntryListener;
return [
'doctrine' => [
'eventmanager' => [
'orm_default' => [
'subscribers' => [
DiscriminatorEntryListener::class,
],
],
],
В дальнейшем для добавления в DiscriminatorMap значения из сущности потомка, необходимо использовать аннотацию Nnx\Doctrine\Annotation\DiscriminatorEntry
<?php
namespace Nnx\Doctrine\PhpUnit\TestData\DiscriminatorEntry\TestModule1\Entity\Overload;
use Doctrine\ORM\Mapping as ORM;
use Nnx\Doctrine\Annotation as NNXD;
use Nnx\Doctrine\PhpUnit\TestData\DiscriminatorEntry\TestModule1\Entity\RootEntity as BaseEntity;
/**
* Class RootEntity
*
* @ORM\Entity()
* @NNXD\DiscriminatorEntry(value="overload")
*/
class RootEntity extends BaseEntity
{
// ...
}