Doubt about how to share information

Asked

Viewed 104 times

1

Create a static control for the menus, the goal 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 constructor of each of the Bundle, be able to register their respective menus, however, I need to solve the route and if possible 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')

doesn’t 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 how to do I accept, because I use the Symfony shortly and it is very likely that I am reinventing the wheel.

1 answer

1


It looks better if you use Services and also the Knpmenubundle and each of your Bundles can make contributions to setting up the Bundle context at each run.

Behold 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 configuration of the service

# 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 the other Bundles, making change in the context.

  • I will study these responses, however, I am only interested if by invoking the menu in the first it already has the data of all the other Bundles, If I have 5 Bundles, for example. If a call the menu only in the first, the entity that stores the menus should already have the menus of the other Bundles, so I exemplified the use of the constructor, I also need to maintain the Menu entity, but I’ll see this example, because I do not know, it may be really the solution.

  • It is a slightly longer path, as you need to enter an observation pattern, so that your Bundles have changed the menu object before your call. Study the SF2 layers and you will learn a lot!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.