Doubt about sharing symfony bundle information

1

Create a static control for the menus, the purpose was for each Bundle to register its menu item.

<?php

namespace Test\RegisterBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Doctrine\Common\Collections\ArrayCollection;
use Test\RegisterBundle\Entity\Menu;

class MenuController extends Controller {

    const STANDARD_CONTAINER = '#content-wrapper';

    /**
     *
     * @var ArrayCollection 
     */
    private static $menus;

    public static function register(Menu $m) {
        if (empty(self::$menus)) {
            self::$menus = new ArrayCollection();
        }
        self::$menus->add($m);
    }

    public static function getAll() {
        return self::$menus;
    }

    /**
     * 
     * @param ArrayCollection $menus
     * @param array $navs
     * @return Menu
     */
    private static function getMenuByNavFromCollection(ArrayCollection $menus, $navs) {
        $e = array_shift($navs);
        foreach (self::$menus as $m) {
            if (!$m instanceof Menu) {
                continue;
            }
            if ($m->getName() != $e) {
                continue;
            }
            if (empty($navs)) {
                return $m;
            } else if ($m->getSubmenu()->count() == 0) {
                return null;
            } else {
                return self::getMenuByNavFromCollection($m->getSubmenu(), $navs);
            }
        }
        return null;
    }

    /**
     * @param string $location
     * @return Menu
     */
    public static function getMenuByNav($location) {
        $navs = explode('::', $location);
        if (empty($navs) || empty(self::$menus)) {
            return null;
        }
        return self::getMenuByNavFromCollection(self::$menus, $navs);
    }
}



<?php
namespace Test\RegisterBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Table(name="menu")
 * @ORM\Entity
 */
class Menu {

    const TYPE_SIDEBAR = 'sidebar';
    const TYPE_LABEL = 'label';

    function __construct() {
        $this->submenu = new ArrayCollection();
    }

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

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

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

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

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

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

    /**
     * @ORM\Column(name="description", type="text", nullable=true)
     * @var string 
     */
    private $description;

    /**
     * @ORM\Column(name="created", type="datetime", nullable=true)
     * @var \DateTime
     */
    private $created;

    /**
     * @ORM\Column(name="modified", type="datetime", nullable=true)
     * @var \DateTime
     */
    private $modified;

    /**
     * @ORM\OneToMany(targetEntity="Menu", mappedBy="parent")
     * */
    private $submenu;

    /**
     * @ORM\ManyToOne(targetEntity="Menu", inversedBy="submenu")
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
     */
    private $parent;

    /**
     * @ORM\ManyToMany(targetEntity="Module", inversedBy="menu")
     * @ORM\JoinTable(name="menu_modules")
     */
    private $module;

    public function getId() {
        return $this->id;
    }

    public function getName() {
        return $this->name;
    }

    public function getUri() {
        return $this->uri;
    }

    public function getMode() {
        return empty($this->mode) ? self::TYPE_SIDEBAR : $this->mode;
    }

    public function setMode($mode) {
        $this->mode = $mode;
        return $this;
    }

    public function getIcon() {
        return $this->icon;
    }

    public function getDescription() {
        return $this->description;
    }

    public function getCreated() {
        return $this->created;
    }

    public function getModified() {
        return $this->modified;
    }

    /**
     * 
     * @return ArrayCollection
     */
    public function getSubmenu() {
        return $this->submenu;
    }

    /**
     * 
     * @return Menu
     */
    public function getParent() {
        return $this->parent;
    }

    public function getModule() {
        return $this->module;
    }

    public function setId($id) {
        $this->id = $id;
        return $this;
    }

    public function setName($name) {
        $this->name = $name;
        return $this;
    }

    public function setUri($uri) {
        $this->uri = $uri;
        return $this;
    }

    public function setIcon($icon) {
        $this->icon = $icon;
        return $this;
    }

    public function setDescription($description) {
        $this->description = $description;
        return $this;
    }

    public function setCreated(\DateTime $created) {
        $this->created = $created;
        return $this;
    }

    public function setModified(\DateTime $modified) {
        $this->modified = $modified;
        return $this;
    }

    public function setSubmenu($submenu) {
        $this->submenu = $submenu;
        return $this;
    }

    public function setParent($parent) {
        $this->parent = $parent;
        return $this;
    }

    public function setModule($module) {
        $this->module = $module;
        return $this;
    }

    public function getRemote() {
        return $this->remote;
    }

    public function setRemote($remote) {
        $this->remote = $remote;
        return $this;
    }

    public function addMenu(Menu $menu) {
        $this->submenu[] = $menu;
        return $this;
    }

}

My intention was in the specific builder of each Bundle, to register their respective menus, however, I need to resolve the route and if possible I wanted access to Doctrine also to register these menus in persistence.

Arqui is an illustration of the problem and what I would like to do, I know that

  

$ this-> get ('router') -> generate ('register_profile_view')

does not exist in the context below, it's just an example of what I needed.

<?php

namespace Test\RegisterBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;
use SBCorp\RegisterBundle\Controller\MenuController;
use SBCorp\RegisterBundle\Entity\Menu;

class RegisterBundle extends Bundle {

    function __construct() {
        $mProfile = new Menu();
        $mProfile->setIcon('fa-th')
                ->setName('My Profile')
                ->setRemote('#content-wrapper')
                ->setUri($this->get('router')->generate('register_profile_view'));


        MenuController::register($mProfile);

    }

}

If you have another suggestion of how to do it, I accept it, because I use Symfony very soon and it is very probable that I am reinventing the wheel.

    
asked by anonymous 11.07.2014 / 01:27

1 answer

1

It's best if you use Services as well as KnpMenuBundle and each Bundle of yours can make contributions to the assembly of the bundle context at each execution.

See Creating Menus as Services

<?php
// src/Acme/MainBundle/Menu/MenuBuilder.php

namespace Acme\MainBundle\Menu;

use Knp\Menu\FactoryInterface;
use Symfony\Component\HttpFoundation\Request;

class MenuBuilder
{
    private $factory;

    /**
     * @param FactoryInterface $factory
     */
    public function __construct(FactoryInterface $factory)
    {
        $this->factory = $factory;
    }

    public function createMainMenu(Request $request)
    {
        $menu = $this->factory->createItem('root');

        $menu->addChild('Home', array('route' => 'homepage'));
        // ... add more children

        return $menu;
    }
}

and the service configuration

# src/Acme/MainBundle/Resources/config/services.yml
services:

    acme_main.menu.sidebar:
        class: Knp\Menu\MenuItem
        factory_service: acme_hello.menu_builder
        factory_method: createSidebarMenu
        arguments: ["@request"]
        scope: request
        tags:
            - { name: knp_menu.menu, alias: sidebar } # Named "sidebar" this time

and of course, access to this service can be done by other bundles, making changes in context.

    
11.07.2014 / 15:21