问题
What's the best way to create breadcrumbs using knpmenu bundle in symfony 2.1.x ? Aside from using 3-rd party bundles.
UPDATE:
Hi, theunraveler, sorry for late answer. Now I've been following your example and I'm stuck at one moment. Here, code below throws an exception, that
Missing argument 2 for Acme\DemoBundle\Menu\MenuBuilder::getBreadCrumbs()
{% set item = knp_menu_get('main') %}
{{ knp_menu_render(item) }}
{% block breadcrumbs %}
{% set breadcrumbs = knp_menu_get('breadcrumbs', [], {'request': app.request, 'menu': item }) %}
{{ dump(breadcrumbs) }}
{% endblock %}
Why it doesn't accepts "item" variable?
回答1:
The Knp\Menu\MenuItem
class has a getBreadcrumbsArray()
method. It should return an array of items in the current active menu trail. If you are on an earlier version of KnpMenu
(<= 1.1.2, I think), the returned array will be in the form of label => uri
. Otherwise, it will be an array with each item having keys label
, uri
, and item
.
To find the current menu item, you'll probably want to create a method in your controller (or somewhere else, if it makes more sense for your project) that looks something like this:
public function getCurrentMenuItem($menu)
{
foreach ($menu as $item) {
if ($item->isCurrent()) {
return $item;
}
if ($item->getChildren() && $current_child = $this->getCurrentMenuItem($item)) {
return $current_child;
}
}
return null;
}
From there, you can call getBreadcrumbsArray()
on the returned value:
$this->getCurrentMenuItem($your_menu)->getBreadcrumbsArray();
I guess what I would do ultimately is create a Twig extension that registers a breadcrumbs
global, and put the getCurrentMenuItem()
method in there. That way, you can have the breadcrumb
variable in all of your templates without having to manually render it in each controller.
Source: https://github.com/KnpLabs/KnpMenu/blob/master/src/Knp/Menu/MenuItem.php#L544.
回答2:
Since version 2.0
, getBreadcrumbsArray
has been moved to Knp\Menu\Util\MenuManipulator
.
Possible workout to this solution is to create a twig extension:
<?php
namespace Kimwild\CommonBundle\Twig;
use Knp\Menu\Util\MenuManipulator;
use Knp\Menu\ItemInterface;
class MenuManipulatorExtension extends \Twig_Extension
{
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('menu_manipulator', array($this, 'menuManipulator')),
);
}
public function menuManipulator(ItemInterface $item)
{
$manipulator = new MenuManipulator();
return $manipulator->getBreadcrumbsArray($item);
}
public function getName()
{
return 'menu_manipulator';
}
}
Register twig extension:
kimwild_common.menu_manipulator_extension:
class: Kimwild\CommonBundle\Twig\MenuManipulatorExtension
public: false
tags:
- { name: twig.extension }
In breadcrumb.html.twig:
{% block root %}
{%- for link in menu_manipulator(item) %}
/* whatever you want to do ... */
{%- endfor %}
{% endblock %}
回答3:
Since KnpMenu 2.1
, there is a new twig function: knp_menu_get_breadcrumbs_array
You can take a look at my gist: https://gist.github.com/fsevestre/b378606c4fd23814278a
I added a new twig function knp_menu_get_current_item
, which retrieve the current menu item and work fine with the knp_menu_get_breadcrumbs_array
function.
--
Edit:
With KnpMenu 2.2
, you can now do:
<ol class="breadcrumb">
{% for breadcrumb_item in knp_menu_get_breadcrumbs_array(knp_menu_get_current_item('main')) %}
{% if not loop.last %}
<li><a href="{{ breadcrumb_item.uri }}">{{ breadcrumb_item.label }}</a></li>
{% else %}
<li class="active">{{ breadcrumb_item.label }}</li>
{% endif %}
{% endfor %}
</ol>
https://github.com/KnpLabs/KnpMenu/blob/master/doc/02-Twig-Integration.markdown#functions
The knp_menu_get_current_item('main')
Twig function will retrieve the current menu item, for the main
menu.
来源:https://stackoverflow.com/questions/13359366/creating-breadcrumbs-in-symfony-2-1-using-knpmenu-bundle