Сопоставленный Супер Класс 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")

Это все.

Другие вопросы по тегам