I'm working with symfony 3.3 and knpMenu 2.2 I have register a menu builder as service
lilworks_store.menu_builder:
class: LilWorks\StoreBundle\Menu\MenuBuilder
arguments: ["@knp_menu.factory","@request_stack"]
tags:
- { name: knp_menu.menu_builder, method: createMainMenu, alias: main } # The alias is what is used to retrieve the menu
I can render a simple menu without any issue. But when I try to had route with parameters I have a error
An exception has been thrown during the rendering of a template ("Parameter "customer_id" for route "customer_show" must match "[^/]++" ("" given) to generate a corresponding URL.").
I can avoid this within a condition on $this->requestStack->getCurrentRequest()->get('customer_id') to create the child only if the route parameter is available.
class MenuBuilder
{
private $factory;
private $requestStack;
/**
* @param FactoryInterface $factory
*
* Add any other dependency you need
*/
public function __construct(FactoryInterface $factory,RequestStack $requestStack)
{
$this->factory = $factory;
$this->requestStack = $requestStack;
}
public function createMainMenu(array $options)
{
$menu = $this->factory->createItem('root');
$menu->addChild('storebundle.menu.storehome', array('route' => 'site_homepage'));
$menu->addChild('storebundle.menu.adminhome', array('route' => 'lilworks_store_homepage'));
$userMenuCat = $menu->addChild('storebundle.menu.cat.user');
$customerMenu = $userMenuCat->addChild('storebundle.menu.customer', array('route' => 'customer_index'));
$customerMenu->addChild('storebundle.menu.customer.new', array('route' => 'customer_new'));
if($this->requestStack->getCurrentRequest()->get('customer_id')){
$customerMenu->addChild('storebundle.menu.customer.show', array('route' => 'customer_show', 'routeParameters' => array('customer_id' => $this->requestStack->getCurrentRequest()->get('customer_id'))));
$customerMenu->addChild('storebundle.menu.customer.edit', array('route' => 'customer_edit', 'routeParameters' => array('customer_id' => $this->requestStack->getCurrentRequest()->get('customer_id'))));
}
$userMenu = $userMenuCat->addChild('storebundle.menu.user', array('route' => 'user_index'));
$userMenu->addChild('storebundle.menu.user.new', array('route' => 'user_new'));
if($this->requestStack->getCurrentRequest()->get('user_id')){
#$userMenu->addChild('storebundle.menu.user.show', array('route' => 'user_show', 'routeParameters' => array('user_id' => $this->requestStack->getCurrentRequest()->get('user_id'))));
#$userMenu->addChild('storebundle.menu.user.edit', array('route' => 'user_edit', 'routeParameters' => array('user_id' => $this->requestStack->getCurrentRequest()->get('user_id'))));
}
$sessionMenu = $userMenuCat->addChild('storebundle.menu.session', array('route' => 'session_index'));
if($this->requestStack->getCurrentRequest()->get('session_id')){
#$sessionMenu->addChild('storebundle.menu.session.show', array('route' => 'session_show', 'routeParameters' => array('session_id' => $this->requestStack->getCurrentRequest()->get('session_id'))));
#$sessionMenu->addChild('storebundle.menu.session.edit', array('route' => 'session_edit', 'routeParameters' => array('session_id' => $this->requestStack->getCurrentRequest()->get('session_id'))));
}
$orderMenuCat = $menu->addChild('storebundle.menu.cat.order');
$orderMenu = $orderMenuCat->addChild('storebundle.menu.order', array('route' => 'order_index'));
$orderMenu->addChild('storebundle.menu.order.new', array('route' => 'order_new'));
if($this->requestStack->getCurrentRequest()->get('order_id')){
#$orderMenu->addChild('storebundle.menu.order.show', array('route' => 'order_show', 'routeParameters' => array('order_id' => $this->requestStack->getCurrentRequest()->get('order_id'))));
#$orderMenu->addChild('storebundle.menu.order.edit', array('route' => 'order_edit', 'routeParameters' => array('order_id' => $this->requestStack->getCurrentRequest()->get('order_id'))));
}
$couponMenu = $orderMenuCat->addChild('storebundle.menu.coupon', array('route' => 'coupon_index'));
$couponMenu->addChild('storebundle.menu.coupon.new', array('route' => 'coupon_new'));
if($this->requestStack->getCurrentRequest()->get('coupon_id')){
#$couponMenu->addChild('storebundle.menu.coupon.show', array('route' => 'coupon_show', 'routeParameters' => array('coupon_id' => $this->requestStack->getCurrentRequest()->get('coupon_id'))));
#$couponMenu->addChild('storebundle.menu.coupon.edit', array('route' => 'coupon_edit', 'routeParameters' => array('coupon_id' => $this->requestStack->getCurrentRequest()->get('coupon_id'))));
}
$depositSaleMenu = $orderMenuCat->addChild('storebundle.menu.depositsale', array('route' => 'coupon_index'));
$depositSaleMenu->addChild('storebundle.menu.depositsale.new', array('route' => 'depositSale_new'));
if($this->requestStack->getCurrentRequest()->get('depositsale_id')){
#$depositSaleMenu->addChild('storebundle.menu.coupon.show', array('route' => 'depositSale_show', 'routeParameters' => array('depositsale_id' => $this->requestStack->getCurrentRequest()->get('depositsale_id'))));
#$depositSaleMenu->addChild('storebundle.menu.coupon.edit', array('route' => 'depositSale_edit', 'routeParameters' => array('depositsale_id' => $this->requestStack->getCurrentRequest()->get('depositsale_id'))));
}
return $menu;
}
In all exemple I have seen nobody use this condition to build the menu with parameted route. What I'm doing wrong?
You aren't doing anything wrong. If you need information from the request, such as a parameter from the URL, or the username from a service (like
$this->tokenStorage->getToken()->getUser();) then arrange to get it, and use it.In my own code, I've fetched the user (as above - assuming it exists) an use it to make a link:
For you, the only thing I would particularly do was to get the various parameters ('user_id' and so on) once into a variable and then use it, rather than continually re-fetching it (that's a little too verbose in my opinion). That and just split the menu service up a little into smaller functions to make it a little easier to understand as well - but that is more style and code standards than the original question.