有时候,我们并不希望,我们在twig模板中的每个导航加亮的判断条件,都在控制器的action中输出,因为我们会浪费大量的时间和精力去写重复的代码。
(上面图片只是一个示意图)这种情况如何去做呢?其实很多解决方案,这根据你的场景不同,解决方案也有所不同。
今天介绍一种方法,我们根据controller来判断导航菜单的加亮,主要你可以学习“如何设置前后过滤程序”。
很多时候,我更推荐你使用
KnpMenuBundle,很棒的bundle,可以解决我们很多的烦恼。
了解如何设置前后过滤程序
首先,你要会学会 “如何设置前后过滤程序”,这个很重要,你不光会在今天用到,你还可能在其他场景中用到。
必要的了解和准备
我们以一个模拟实例作为参照,打个比方,我们的导航是按照我们的控制器进行分类的,并且加亮的规则也是按照分类来进行的。也就是说,我们访问哪个分类,对应的控制器就会给定默认模板加亮的值。
首先我们要有一个标准的DocController
1 |
class DocController extends Controller |
此控制器对应我们的分类菜单,当然我们还会有(组件控制器),CMF控制器等。
创建一个接口
根据,如何设置前后过滤程序的指导,我们创建一个接口:
1 2 3 4 5 6 7 |
namespace AppBundle\Controller; interface MenuDocController { } |
下一步我们让我们的控制器实现这个接口:
1 |
class DocController extends Controller implements MenuDocController |
接口只是识别的一个标志而已,后面你就会明白了。
创建事件监听
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
namespace AppBundle\EventListener; use AppBundle\Controller\MenuDocController; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; use Symfony\Component\HttpKernel\Event\GetResponseEvent; class MenuListener { public function onKernelController(FilterControllerEvent $event){ $controller = $event->getController(); $request=$event->getRequest(); /* * $controller passed can be either a class or a Closure. * This is not usual in Symfony but it may happen. * If it is a class, it comes in array format */ if (!is_array($controller)) { return; } if ($controller[0] instanceof MenuDocController) { $request->attributes->set('MenuValue', "doc"); } } } |
你发现了 if ($controller[0] instanceof MenuDocController) 这句的含义了吗?这个接口就在这里用到了。
这里在request对象中,设置了一个属性,这个属性就是标识现在菜单的状态。
下面注册监听器:
1 2 3 4 5 |
app.menu.action_listener: class: AppBundle\EventListener\MenuListener arguments: [] tags: - { name: kernel.event_listener, event: kernel.controller, method: onKernelController } |
模板判断
1 |
<li {% if app.request.attributes.get('MenuValue') == "doc" %} class="active" {% endif %}><a href="{{ path("doc_index") }}">中文文档</a> |