Сопоставленный Супер Класс Symfony2.2
Я создал Пакет (называемый MYBUNDLE) всего с двумя объектами: Меню и Группа. Оба были объявлены как mappedSuperclass, потому что мне нужно, чтобы этот пакет можно было использовать для других проектов. Как условие, проекты должны расширяться от этих классов, чтобы настраивать их, устанавливая имя таблицы или добавляя некоторые поля. Например:
Занятия в MYBUNDLE:
class Group{
protected $id;
protected $menus;
}
class Menu{
protected $id;
protected $groups;
}
YML для отображения моих сущностей из MYBUNDLE
Project\MYBUNDLE\Entity\Menu:
type: mappedSuperclass
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
Project\MYBUNDLE\Entity\Group:
type: mappedSuperclass
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
manyToMany:
menus:
targetEntity: Menu
joinTable:
name: sf_group_menu
joinColumns:
sf_group_id:
referencedColumnName: id
inverseJoinColumns:
sf_menu_id:
referencedColumnName: id
Занятия в моей детской пачке:
use Project\MYBUNDLE\Entity\Group as TGroup;
/**
* @ORM\Entity
* @ORM\Table(name="sf_group")
*/
class Group extends TGroup
{ }
use Project\MYBUNDLE\Entity\Menu as TMenu;
/**
* @ORM\Entity
* @ORM\Table(name="sf_menu")
*/
class Menu extends TMenu
{ }
Однако у каждого из этих двух классов есть свойство создавать множество связей между ними (поскольку mappedSuperclass не допускает обратную сторону, моя связь является множеством однонаправленных).
Мне нужно сделать запрос внутри MYBUNDLE. Запрос, объединяющий обе таблицы с множеством ассоциаций. Причина, по которой я хочу сделать этот запрос внутри MYBUNDLE, заключается в том, что в этом пакете есть служба, которая рисует меню, депонируемое в группе или группах. Этот метод должен быть упрощен из этого комплекта, чтобы другие комплекты могли использовать его, и мне не нужно внедрять его в каждый поднабор.
Мое частичное решение было сделать часть конфигурации для моего MYBUNDLE, что-то вроде:
mybundle:
menu_entity:
name: MyprojectChildBundle\Entity\Menu
group_entity:
name: MyprojectChildBundle\Entity\Group
С этой конфигурацией я могу использовать хранилище дочернего пакета внутри MYBUNDLE, с этим:
$this->em->getRepository("MyprojectChildBundle:Group")-findAll();
Все работает, когда я делаю запрос без объединений. С другой стороны, когда я делаю это:
$repo = $this->em->getRepository("MyprojectChildBundle:Group");
$result = $repo->createQueryBuilder("c")
->select('c, d')
->join("c.menus", "d")->getQuery()->getResult();
return $result
Все терпит неудачу, потому что сформированный SQL пытается найти таблицу под названием "Меню", которая не существует, потому что она называется "sf_menu". Таблица Group правильно изменена на "sf_group", потому что я использую репозиторий моего ребенка. Однако, используя этот репозиторий, просто измените имя этого класса, но не объединяемых таблиц.
Как я могу сделать такой запрос внутри MYBUNDLE? Большое спасибо.
1 ответ
Наконец я нашел решение:)
Мне пришлось создать еще 2 класса в качестве моей модели. Эти классы должны иметь всю отображающую базу данных и должны быть объявлены как одно наследование, как это:
#src\Myproject\MYBUNDLE\Model\Menu
/**
* @ORM\Entity
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap({"menu1" = "Myproject\MYBUNDLE\Entity\Menu", "menu2" = "Menu"})
*/
abstract class Menu {
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
// Other fields
}
То, что вы должны сделать с обоими объектами (меню и группы). Преимущество этой реализации состоит в том, что вы не теряете никаких ассоциаций, как раньше, потому что объявляете их как mappedSuperClasss.
Затем вы должны объявить одну сущность для каждого класса модели и объявить их как MappedSuperClass. Они должны выглядеть так:
#src\Myproject\MYBUNDLE\Entity\Menu
use Doctrine\ORM\Mapping as ORM;
use Tixpro\TMenuBundle\Model\Menu as BaseMenu;
/** @ORM\MappedSuperclass */
class Menu extends BaseMenu
{
}
С этой реализацией вы убедитесь, что не потеряете никакой ассоциации. Кроме того, любая сущность может выходить за пределы вашего класса сущностей, чтобы добавлять дополнительные поля и настраивать их. Например:
#src\Project\ChildBundle\Entity\Menu
use Myproject\MYBUNDLE\Entity\Menu as TMenu;
/**
* @ORM\Entity
* @ORM\Table(name="sf_menu")
*/
class Menu extends TMenu{
//put your code here
}
Не забудьте настроить параметры в config.yml для использования MYBUNDLE.
mybundle:
menu_entity:
name: MyprojectChildBundle\Entity\Menu
group_entity:
name: MyprojectChildBundle\Entity\Group
если вы этого не сделаете, вы не сможете узнать репозиторий внутри MYBUNDLE и, следовательно, вы не сможете сделать объединенные запросы в свой MYBUNDLE.
Наконец, после установки параметров и реализации этой возможности вы можете использовать объединенные запросы внутри своего MYBUNDLE, например:
$repo = $this->em->getRepository("MyprojectChildBundle:Menu");
$result = $repo->createQueryBuilder("wa")
->select('wa, da')
->join("wa.roles", "da")
Это все.