利用 步骤1
Creat在\module\Application\Module.php
<?php
/**
* Zend Framework (http://framework.zend.com/) ...*/
namespace Application;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
class Module
{
// ** snip **
public function getViewHelperConfig() {
return array(
'invokables' => array(
// The 'key' is what is used to call the view helper
'NewMenu' => 'Application\View\Helper\NewMenu',
)
);
}
}
步骤3版自定义视图助手应用程序模块src\Application\View\Helper\NewMenu.php
NewMenu.php
<?php
namespace Application\View\Helper;
// I'm extending this class, need to include it
use Zend\View\Helper\Navigation\Menu;
// Include namespaces we're using (from Zend\View\Helper\Navigation\Menu)
use RecursiveIteratorIterator;
use Zend\Navigation\AbstractContainer;
use Zend\Navigation\Page\AbstractPage;
class NewMenu extends Menu
{
// copied fromZend\View\Helper\Navigation\Menu
protected function renderNormalMenu(...){}
// copied from Zend\View\Helper\Navigation\Menu
public function htmlify(...){}
}
步骤2
注册新视图助手下与getViewHelperConfig()
在我的layout.phtml
脚本中,我得到我的导航容器并将它传递给NewMenu视图助手。我还设置了一些选项,例如添加父级<ul>
类名称而不是转义标签,以便我可以将Bootstrap使用的标准'dropdown caret'(即<b class="caret"></b>
)添加到带有下拉菜单的标签。
$container = $this->navigation('navigation')->getContainer();
echo $this->NewMenu($container)->setUlClass('nav navbar-nav')->escapeLabels(false);
中场
在这一点上,我们应该有更多或更少的只是复制了菜单视图助手。它应该像标准的View Helper一样产生一个导航。
步骤4
在NewMenu.php
类,我删除$addClassToListItem
代码,以避免它从由事故放置类错误的元件上。
protected function renderNormalMenu(...)
// Add CSS class from page to <li>
//if ($addClassToListItem && $page->getClass()) {
// $liClasses[] = $page->getClass();
//}
公共职能htmlify(...)
// Always apply page class to <a> tag. We'll use a diff. method for <li>
//if ($addClassToListItem === false) {
$attribs['class'] = $page->getClass();
//}
步骤5
添加一个方法来CSS类名适用于<li>
标签,因为我们去掉了$addClassTolistItem
方法。我们只需使用Page类的能力,具有自定义属性,并做到这一点:
保护功能renderNormalMenu现在
// Is page active?
if ($isActive) {
$liClasses[] = 'active';
}
if($wrapClass = $page->get('wrapClass')){
$liClasses[] = $wrapClass;
}
...
,在我们的导航配置文件,我们只需添加一个名为wrapClass
应用CSS属性类包装元素(<li>
)。
设置\自动加载\ global.php
...
'navigation' => array(
'default' => array(
...
array(
'label' => 'Products <b class="caret"></b>',
'route' => 'products',
'wrapClass' => 'dropdown', // class to <li>
'class' => 'dropdown-toggle', // class to <a> like usual
'pages' => array(
array(
'label' => 'Cars',
'route' => 'products/type',
...
),
...
),
),
...
步骤6
添加到对<a>
附加属性等data-*
的能力。对于Bootstrap 3,例如,您需要data-toggle="dropdown"
。
公共职能htmlify(...)
// get attribs for element
$attribs = array(
'id' => $page->getId(),
'title' => $title,
);
// add additional attributes
$attr = $page->get('attribs');
if(is_array($attr)){
$attribs = $attribs + $attr;
}
在您的配置文件,你现在可以添加一个属性与附加属性的数组:
配置\自动加载\全球。 PHP
...
'navigation' => array(
'default' => array(
...
array(
'label' => 'Products <b class="caret"></b>',
'route' => 'products',
'wrapClass' => 'dropdown', // class to <li>
'class' => 'dropdown-toggle', // class to <a> like usual
'attribs' => array(
'data-toggle' => 'dropdown', // Key = Attr name, Value = Attr Value
),
'pages' => array(
array(
'label' => 'Cars',
'route' => 'products/type',
...
),
...
),
),
...
步骤7
添加在嵌套列表容器上放置类名的功能(例如, <ul>
)。
保护功能renderNormalMenu()
if ($depth > $prevDepth) {
// start new ul tag
if ($ulClass && $depth == 0) {
$ulClass = ' class="' . $ulClass . '"';
}
// Added ElseIf below
else if($ulClass = $page->get('pagesContainerClass')){
$ulClass = ' class="' . $ulClass . '"';
}
else {
$ulClass = '';
}
$html .= $myIndent . '<ul' . $ulClass . '>' . self::EOL;
原来的代码基本上说:“如果这是第一次<ul>
,有一个UL类,添加它,别的什么也不做。所以,我增加了一个额外的检查。就是说,如果一个属性叫pagesContainerClass
是可用的,对类适用于<ul>
以及
这意味着我们需要在我们的配置中添加右侧页面的属性:
config \ autoload \ global。PHP
...
'navigation' => array(
'default' => array(
...
array(
'label' => 'Products <b class="caret"></b>',
'route' => 'products',
'wrapClass' => 'dropdown', // class to <li>
'class' => 'dropdown-toggle', // class to <a> like usual
'attribs' => array(
'data-toggle' => 'dropdown', // Key = Attr name, Value = Attr Value
),
'pages' => array(
array(
'label' => 'Cars',
'route' => 'products/type',
// Give child <ul> a class name
'pagesContainerClass' => 'dropdown-menu',
...
),
...
),
),
...
重要的是注意,UL类需要放在一个孩子的第一个子页面是因为条件语句被包裹在以下条件:
if ($depth > $prevDepth) {
// start new ul tag
...
}
第一后孩子被调用,$ dept = $ prevDepth和嵌套的<ul>
已经被发送到字符串缓冲区。
该解决方案还没有被严格的测试,但这个想法是简单地取当前菜单视图助手,和过载的两个必要方法和仅略微修改了。
我试着使用setPartial()
,但只有具有<li>
代的帮助下,该公司仍使用菜单视图助手htmlify()
方法(所有这些都在布拉姆的讨论上面提到的)。
因此,与使这些小tweeks的方法和使用Page类的具有自定义属性的能力,我可以添加一些额外的逻辑来获得关于<li>
,<a>
和嵌套<ul>
类的类名,以及添加额外的属性的<a>
元素,所以我可以配置我的Zend\Navigation
从配置吐出来,基本上,Bootstrap 3 Navbar标记。
最终布局则看起来就像这样:
<nav class="navbar navbar-default navbar-static-top" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="collapse navbar-collapse navbar-ex1-collapse">
<?php
// Use Zend\Navigation to create the menu
$container = $this->navigation('navigation')->getContainer();
echo $this->NewMenu($container)->setUlClass('nav navbar-nav')->escapeLabels(false);
?>
</div><!-- /.navbar-collapse -->
</nav>
我一直运行到的烦恼是更好地了解PHP命名空间,并具有需要包括相应的合格的命名空间在我的自定义视图助手,即使我正在扩展它。
的另一个问题,是导航视图助手可以调用菜单视图助手从本身就像这样:
$this->navigation('navigation')->menu();
这是行不通的:
$this->navigation('navigation')->NewMenu();
我想是因为与NewMenu
没有在Navigation View Helper类中注册的命名空间问题,我不打算仅仅为此而扩展它。
所以,希望这(长)答案将有助于其他谁正在努力满足这种需求。
干杯!
谢谢您的回答。 是 - 我可以添加“数据测试” =>“blahblah”和检索它作为$页面级>的get(“数据测试”) - 但仍无法将其追加为属性为 .. ..我必须重写htmlify到那个? – 2013-02-24 00:56:20
是的,你需要扩展菜单视图助手,并且只能覆盖htmlify方法。看看htmlify方法,你会看到数组定义的attrib。你可以在那里添加你的自定义属性。看到我的【答案】(http://stackoverflow.com/questions/15017288/injecting-custom-navigation-using-a-view-helper-through-the-servicemanager/15019924#15019924)上的另一SO如何注册质疑您自己的导航视图助手。 – 2013-02-24 01:31:35
感谢您的回复。所以 - 我的菜单实际上有2个层次的深度...所以基本上 - 视图部分 - 我必须递归迭代容器 - 正确吗?我不能只是简单地对页面项目进行foreach ... – 2013-02-24 04:01:21