N
N
Nikolai Egorov2019-02-17 15:59:19
symfony
Nikolai Egorov, 2019-02-17 15:59:19

How to make a connection of one table field with several entities (entity)?

I ran into a problem that baffled me. It seems that everything just seemed - you need to make a multi-level menu manager in the admin panel. The problem is that each of the menu items takes the link itself (URL) from the entity (Entity) that is attached to this menu item. There are several types of entities, respectively, and there are also several classes of the menu item (MenuItem):

  • MenuItemPage has a link to the Page entity (there will be a link to a single page)
  • MenuItemCategory has a relationship with the Category entity (there will be a link to the category)
  • ... other types
  • finally, the simplest, MenuItemSimple has no links and you can set an arbitrary link for it

The result should be a menu with a similar structure:
  • MenuItemSimple - menu root, not linked to entities
    • MenuItemPage - Link to the page
    • MenuItemPage - Link to the page
    • MenuItemSimple - further the root of the category submenu, without being tied to an entity
      1. MenuItemCategory - Category link
      2. MenuItemCategory - Category link
      3. MenuItemCategory - Category link
      4. MenuItemCategory - Category link


The code turned out like this
/**
 * @ORM\Entity
 * @ORM\Table("menus")
 * @Gedmo\Mapping\Annotation\Tree(type="nested")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="discriminator", type="string")
 * @ORM\DiscriminatorMap({
 *     "simple" = "MenuItemSimple",
 *     "page" = "MenuItemPage",
 *     "article" = "MenuItemArticle",
 *     "category" = "MenuItemCategory"
 * })
 * @ORM\Entity(repositoryClass="App\Repository\MenuItemRepository")
 */
abstract class MenuItem
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=256, nullable=true)
     */
    private $titleLink;

    /**
     * Href property for link
     *
     * @ORM\Column(type="string", length=256, nullable=true)
     */
    private $hrefLink;

    public function getTitleLink(): ?string
    {
        return $this->titleLink;
    }

    public function setTitleLink(?string $titleLink): self
    {
        $this->titleLink = $titleLink;
        return $this;
    }

    public function getHrefLink(): ?string
    {
        return $this->hrefLink;
    }

    public function setHrefLink(?string $hrefLink): self
    {
        $this->hrefLink = $hrefLink;
        return $this;
    }
}


/**
 * @ORM\Entity
 */
class MenuItemCategory extends MenuItem {

    /**
     * @ORM\ManyToOne(targetEntity="Category")
     */
    private $entity;

    public function getEntity(): ?Category
    {
        return $this->entity;
    }

    public function setEntity(?Category $entity): self
    {
        $this->entity = $entity;
        return $this;
    }
}
/**
 * @ORM\Entity
 */
class MenuItemSimple extends MenuItem {}

Other types of menu item entities are similar to MenuItemCategory - I will not duplicate them.
The essence of the whole problem is that it is not possible to associate the entity_id field with several tables (pages, categories, articles, etc. tables, respectively) - the final menu table is associated with only one. And to spread the menu items across different tables (well, according to the type of connection) is also impossible. menu items should be in the same plate.
The only solution I see so far is to combine all types of menu items (MenuItemPage, MenuItemCategory, MenuItemArticle and others) into one - MenuItem, and instead of one entity field there will be several fields (properties), each of which is associated with its own entity. Thus, the table will have not one field for communication, but as many entities as declared. In short, combine all menu entity types into one. This is even easier to implement ... but not as beautiful as separately.
Help with advice, please!

Answer the question

In order to leave comments, you need to log in

1 answer(s)
F
Flying, 2019-02-17
@nickicool

You are already using DiscriminatorMapwhich is the correct solution for this problem. Nothing now prevents you from having separate properties in inherited classes containing links to specific entities specific to each specific type of menu item. You can also declare getEntity()/ setEntity()in a class as MenuItemabstract, and implement them in child classes. Of course, you will not be able to set types at the language level, but no one will stop you from using PHPDoc to create type hints.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question