2015-04-09 3 views
2

У меня есть следующая проблема - в проекте, у меня есть интерфейс под названием TaggableInterfaceDoctrine ORM - объект реализует интерфейс

interface TaggableInterface { 
    public function addTag(TagInterface $tag); 
    public function deleteTag(TagInterface $tag); 
    public function getTags(); 
} 

Он реализуется некоторыми классами сущностей.

Есть ли хороший способ в Доктрине, которая создает отношения между этими entites и тегами? Если Taggable был не интерфейсом, а классом abstarct, я смог бы решить его с наследованием объекта.

Без доктрины Я бы, вероятно, использовал шаблон дизайна Party/Accountability (http://martinfowler.com/apsupp/accountability.pdf).

ответ

1

Если я правильно понял: вы хотите создать сопоставление и реализацию для интерфейса без использования абстрактного класса и повторяющегося кода.

PHP имеет черты. Вы можете создать черту с общей реализацией интерфейса. Из опыта я знаю, что вы также можете добавить отображение аннотаций доктрины в черту, и все будет хорошо работать.

Создать TaggableTrait. Он ведет себя как класс или интерфейс. Он находится в пространстве имен и будет загружен вашим автозагрузчиком, если вы добавите его с помощью use.

namespace My\Namespace; 

use Doctrine\ORM\Mapping as ORM; 

trait TaggableTrait 
{ 

    /** 
    * @ORM\ManyToMany(targetEntity="Some\Namespace\Entity\Tag") 
    */ 
    protected $tags; 

    public function addTag(TagInterface $tag) 
    { 
     $this->tags->add($tag); 
    } 

    public function removeTag(TagInterface $tag) 
    { 
     $this->tags->removeElement($tags); 
    } 

    public function deleteTag(TagInterface $tag) 
    { 
     $this->removeTag($tag); 
    } 

    public function getTags() 
    { 
     return $this->tags; 
    } 

} 

И в вашем taggable лица:

namespace Some\Namespace\Entity; 

use Some\Namespace\TaggableInterface; 
use My\Namespace\TaggableTrait; 
use Doctrine\ORM\Mapping as ORM; 
//... 

/** 
* @ORM\Entity 
*/ 
class TaggableEntity implements TaggableInterface 
{ 
    use TaggableTrait; 

    public function __construct() 
    { 
     $this->tags = new ArrayCollection(); 
    } 

    // rest of class code 
} 

Обратите внимание, что use внутри класса имеют различное значение. Он добавляет черту и не имеет ничего общего с импортом пространства имен.

Вы всегда должны инициализировать $tags в своем конструкторе, черта не может этого сделать.

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

+0

Спасибо за ваш ответ, интересная идея с использованием черт :) Не могли бы вы показать мне некоторую базовую реализацию одного из методов, например. addTag (я уверен, как создать отношения)? Спасибо – Jadro007

+0

@ Jadro007 Я отредактировал свой ответ. Я также добавил 'removeTag', потому что' removeXXX' является доктриной/symfony. Это гарантирует, что symfony не запутается в ситуациях, таких как редактирование тегов через форму. –

+0

nice :) Я правильно понимаю, что доктрина генерирует объект отношения M: N для каждого объекта, который использует TaggableTrait? – Jadro007

1

В конце концов, я решил использовать более сложное решение, которое требует больше написания кода:

Каждый объект, который реализует Taggable, подключен один-к-одному отношение к его taggable сущности, то есть многие-ко-многим подключен к TagEntity.

Диаграммы классов:

enter image description here


enter image description here

, что создает эту базу данных: enter image description here


enter image description here

Смежные вопросы