Reputation: 241
I have created a Bundle (called MYBUNDLE) with just 2 entities: Menu and Group. Both were declared as mappedSuperclass because I need this bundle could be use for other projects. As a condition, projects will have to extend from these classes to customize them by setting the tables name or adding some fields. For instance:
Classes into MYBUNDLE:
class Group{
protected $id;
protected $menus;
}
class Menu{
protected $id;
protected $groups;
}
YML for mapping my entities from 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
Classes into my child bundle:
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
{ }
However each one of the two classes have a property to make a manytomany association between them (As mappedSuperclass doesn't allow an inverse side, my association is manytomany unidirectional).
I need to make a query inside MYBUNDLE. A query which join both tables with the manytomany association. The reason i want to make this query inside MYBUNDLE, is because this bundle has a service which draws the Menu deppending in the Group or Groups. This method should be facilitate from this bundle, so other bundles could use it and i dont have to implemment in every sub-bundle.
My partial solution was to make a config part for my MYBUNDLE, something like:
mybundle:
menu_entity:
name: MyprojectChildBundle\Entity\Menu
group_entity:
name: MyprojectChildBundle\Entity\Group
With this configuration, I can use the repository of the child bundle inside MYBUNDLE, with this:
$this->em->getRepository("MyprojectChildBundle:Group")-findAll();
Everything works when I make a query without joins. On the other hand, when I do this:
$repo = $this->em->getRepository("MyprojectChildBundle:Group");
$result = $repo->createQueryBuilder("c")
->select('c, d')
->join("c.menus", "d")->getQuery()->getResult();
return $result
Everything fails, because the SQL formed try to look for a table called "Menu" which does not exist because it is called "sf_menu". The table Group is correctly changed to "sf_group" because I am using the Repository of my child. However using this repository just change the name of that class, but not of joined tables.
How could I make this kind of query inside MYBUNDLE? Thanks a lot.
Upvotes: 1
Views: 3328
Reputation: 241
Finally i found the solution :)
I had to create 2 more classes as my model. This classes should have all mapping Database and shoud be declared as single inheritance like this:
#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
}
That you should do with both entities (Menu and Group). The advantage of this implementation is that you don't lose any associations as before, due to declare them as mappedSuperClasss.
Then you should declare one entity per each model class and declare them as MappedSuperClass. They should look like this:
#src\Myproject\MYBUNDLE\Entity\Menu
use Doctrine\ORM\Mapping as ORM;
use Tixpro\TMenuBundle\Model\Menu as BaseMenu;
/** @ORM\MappedSuperclass */
class Menu extends BaseMenu
{
}
With this implementation you make sure not to lose any association. In addition, any entity could extend from your entities class to add more fields and customize them. For instance:
#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
}
Don't forget to configure the params in the config.yml to use MYBUNDLE.
mybundle:
menu_entity:
name: MyprojectChildBundle\Entity\Menu
group_entity:
name: MyprojectChildBundle\Entity\Group
if you dont do this, you couldn't know the repository inside MYBUNDLE and consequently you couldn't make joined queries into your MYBUNDLE.
Finally, after setting your params and making that implementation, you are able to use joined queries inside your MYBUNDLE, like this:
$repo = $this->em->getRepository("MyprojectChildBundle:Menu");
$result = $repo->createQueryBuilder("wa")
->select('wa, da')
->join("wa.roles", "da")
That's all.
Upvotes: 1