Доктрина 2 - Как создать Сущность, имеющую атрибут типа поддерева из Сущности типа основного дерева

У меня есть основной сегмент сущности, в котором есть категории «один ко многим», а в категории есть элементы «один ко многим», поэтому трехуровневая древовидная структура

class Segment
{

    /**
     * @ORM\Id
     */
    protected $id;

    /**
     * @ORM\OneToMany(targetEntity="Category", mappedBy="segment")
     * @ORM\JoinColumn(name="segment_id", referencedColumnName="id")
     */
    protected $categories;
}  

class Category
{

    /**
     * @ORM\Id
     */
    protected $id;

    /**
     * @ORM\ManyToOne(targetEntity="Segment")
     * @ORM\JoinColumn(name="segment_id", referencedColumnName="id")
     */
    protected $segment;

    /**
     * @ORM\OneToMany(targetEntity="Item", mappedBy="category")
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id")
     */
    protected $items;
}

class Item
{

    /**
     * @ORM\Id
     */
    protected $id;

    /**
     * @ORM\ManyToOne(targetEntity="Category")
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id")
     */
    protected $category;
}

Таблицы SQL

CREATE TABLE segment (
    id INT PRIMARY KEY AUTO_INCREMENT NOT NULL,
    name VARCHAR(100) NOT NULL,
)

CREATE TABLE segment_category 
(
    id INT PRIMARY KEY AUTO_INCREMENT NOT NULL,
    segment_id INT NOT NULL,
    name VARCHAR(100) NOT NULL,
    FOREIGN KEY(segment_id) REFERENCES segment(id)
)
CREATE TABLE segment_item 
(
    id INT PRIMARY KEY AUTO_INCREMENT NOT NULL,
    category_id INT NOT NULL,
    name VARCHAR(100) NOT NULL,
    FOREIGN KEY(category_id) REFERENCES segment_category(id)
)

и вот моя юридическая компания, у которой есть подсегмент из сегмента

class Company
{
    /**
     * @ORM\Id
     */
    protected $id;

    /**
     * @ORM\ManyToMany(targetEntity="Segment")
     * -- What here to add? Is this correct ?--
     * @ORM\JoinTable(name="company_segment_linker",
     *      joinColumns={@ORM\JoinColumn(name="company_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="item_id", referencedColumnName="id")}
     * )
     */
    protected $segments;
}

Таблица SQL компании, которая определяет, какой сегмент (а также категории и элементы) принадлежит компании.

CREATE TABLE company_segment_linker 
(
    company_id INT NOT NULL,
    item_id INT NOT NULL,
    FOREIGN KEY(company_id) REFERENCES company(id),
    FOREIGN KEY(item_id) REFERENCES segment_item(id)
) 

Пример структуры данных сегмента (числа представляют собой идентификаторы):

  1. seg1
    1. cat1
      1. item1
      2. item2
      3. item3
    2. cat2
      1. item4
      2. item5
  2. seg2
    1. cat3
      1. item6
    2. cat4
      1. item7
      2. item8

Компания com1, у которой есть подобный подсегмент:

  1. seg1
    1. cat1
      1. item2
      2. item3
    2. cat2
      1. item5
  2. seg2
    1. cat4
      1. item8

Поэтому я бы сохранил только fk_id компании и fk_ids элемента в таблице company_segment_linker
company_id | item_id
1 | 2
1 | 3
1 | 5
1 | 8
потому что из таблицы элементов я могу ссылаться на категорию и из таблицы категорий в сегмент.

Мой вопрос: все ли это возможно в Doctrine2, чтобы создать подсегмент только из внешнего ключа (ов) элемента, и если да, то как написать аннотацию (и)? Или я должен использовать другой подход для этого? Спасибо за вашу помощь. PS: Извините за мой английский: /


person Matej Polák    schedule 27.03.2013    source источник


Ответы (1)


Для своего класса Category вы можете использовать самореференционную ассоциацию OneToMony следующим образом:

/**
 * Category
 *
 * @ORM\Table(name="category")
 * @ORM\Entity(repositoryClass="Category\Entity\Repository\CategoryRepository")
 */

class Category 

{
/**
* @var Integer
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;

/**
 *@var String
 *@ORM\Column(name="cat_name", type="string", length=60, nullable=false)
 * 
 */
private $name;


/**
 * @ORM\OneToMany(targetEntity="Category\Entity\Category", mappedBy="parent")
 **/

private $children;

/**
 *  @ORM\ManyToOne(targetEntity="Category\Entity\Category", inversedBy="children")
 *  @ORM\JoinColumn(name="parent_id", referencedColumnName="id", unique=false, nullable=true)
 **/
private $parent;



public function __construct() {

    $this->children = new \Doctrine\Common\Collections\ArrayCollection();

}

Это создаст для вас одну таблицу, и вы получите свое дерево с помощью этого DQL:

 $ql="SELECT  ca.name, c.name AS child_name FROM Category\Entity\Category ca LEFT JOIN ca.children c WHERE ca.parent IS NULL";
    $query = $em->createQuery($ql);
  $categories = $query->getResult();
person Oskar    schedule 20.10.2013
comment
Так я получаю свои категории и сус-категории, и он неплохо справляется со своей работой в одном из моих модулей. Надеюсь, это сработает для вас. - person Oskar; 20.10.2013