Php 使用Zend框架和引导在二级UL上设置CSS类

Php 使用Zend框架和引导在二级UL上设置CSS类,php,twitter-bootstrap,zend-framework,omeka,Php,Twitter Bootstrap,Zend Framework,Omeka,以下代码将在一级UL上设置类别nav $mainNav = public_nav_main(); $mainNav->setUlClass('nav')->setUlId('main-menu-left'); 然而,我使用引导,所以希望第二级ul有类'下拉菜单' 我似乎找不到一个参考来整理这件事 Zend被用作im使用软件Omeka的基本结构。不幸的是,Omeka没有办法在本地实现这一点,因此我不得不深入研究底层Zend FW,尽管我不想修改太多,因为它可能会被更改。您可能只想基于

以下代码将在一级UL上设置类别nav

$mainNav = public_nav_main();
$mainNav->setUlClass('nav')->setUlId('main-menu-left');
然而,我使用引导,所以希望第二级ul有类'下拉菜单'

我似乎找不到一个参考来整理这件事


Zend被用作im使用软件Omeka的基本结构。不幸的是,Omeka没有办法在本地实现这一点,因此我不得不深入研究底层Zend FW,尽管我不想修改太多,因为它可能会被更改。

您可能只想基于
Zend\u View\u Helper\u Navigation\u HelperAct
编写一个全新的视图帮助程序

在GitHub上寻找基于该抽象的与引导兼容的帮助程序时,我遇到了这样一个问题:它采用了一种有趣的方法,即对开箱即用的帮助程序生成的标记进行后处理

我最近采取了一种稍有不同的方法,刚刚黑掉了
Zend\u View\u Helper\u Navigation\u菜单
。下面是一个统一的差异,总结了这些变化:更好的做法是扩展类

我没有处理子菜单,但是我遇到的问题是

  • 元素添加
    aria角色的方法
  • 在两次渲染菜单时避免冲突-两种表示法-折叠的引导样式和用于较大视口的传统样式-也许采埃孚已经提供了一些解决方案?如果有,我就不会冲我跳
  • 此代码显示了需要调整的方法:

    class MyMenu extends Zend_View_Helper_Navigation_Menu
    {
    
    /**
     * Want a way to set aria role on menu li elements because its 2015 yo
     *
     * @var string
     */
    protected $_liRole = '';
    
    /**
     * Workaround so I can render the damn thing twice on the same page and not collide IDs on the <a>'s
     * Issue arose when adopting bootstrap and rendering both full page nav and collapsed nav bar
     *
     * @var string
     */
    protected $_idAlias = '';
    
    public function setLiRole($liRole)
    {
        if (is_string($liRole)) {
            $this->_liRole = $liRole;
        }
        return $this;
    }
    public function getLiRole()
    {
        return $this->_liRole;
    }
    
    public function setIdAlias($alias)
    {
        $this->_idAlias = $alias;
        return $this;
    }
    public function getIdAlias()
    {
        return $this->_idAlias;
    }
    
    public function renderMenu(Zend_Navigation_Container $container = null, array $options = array())   
    {
        $this->setLiRole($options['liRole']);
        $this->setIdAlias($options['idAlias']);
    
        return parent::renderMenu($container, $options);
    }
    
    /**
     * Returns an HTML string containing an 'a' element for the given page if
     * the page's href is not empty, and a 'span' element if it is empty
     *
     * Overrides {@link Zend_View_Helper_Navigation_Abstract::htmlify()}.
     *
     * @param  Zend_Navigation_Page $page  page to generate HTML for
     * @return string                      HTML string for the given page
     */
    public function htmlify(Zend_Navigation_Page $page)
    {
        // get label and title for translating
        $label = $page->getLabel();
        $title = $page->getTitle();
    
        // translate label and title?
        if ($this->getUseTranslator() && $t = $this->getTranslator()) {
            if (is_string($label) && !empty($label)) {
                $label = $t->translate($label);
            }
            if (is_string($title) && !empty($title)) {
                $title = $t->translate($title);
            }
        }
    
        // get attribs for element
        $attribs = array(
            'id'     => $this->getIdAlias() . $page->getId(),
            'title'  => $title,
            'class'  => $page->getClass()
        );
    
        // does page have a href?
        if ($href = $page->getHref()) {
            $element = 'a';
            $attribs['href'] = $href;
            $attribs['target'] = $page->getTarget();
        } else {
            $element = 'span';
        }
    
        return '<' . $element . $this->_htmlAttribs($attribs) . '><span class="span-nav-icon"></span><span>'
             . str_replace(chr(32), '&nbsp;', $this->view->escape($label))
             . '</span></' . $element . '>';
    }
    
    /**
     * Normalizes given render options
     *
     * @param  array $options  [optional] options to normalize
     * @return array           normalized options
     */
    protected function _normalizeOptions(array $options = array())
    {
        if (isset($options['indent'])) {
            $options['indent'] = $this->_getWhitespace($options['indent']);
        } else {
            $options['indent'] = $this->getIndent();
        }
    
        if (isset($options['ulClass']) && $options['ulClass'] !== null) {
            $options['ulClass'] = (string) $options['ulClass'];
        } else {
            $options['ulClass'] = $this->getUlClass();
        }
    
        if (isset($options['liRole']) && $options['liRole'] !== null) {
            $options['liRole'] = (string) $options['liRole'];
        } else {
            $options['liRole'] = $this->getLiRole();
        }
    
        if (isset($options['idAlias']) && $options['idAlias'] !== null) {
            $options['idAlias'] = (string) $options['idAlias'];
        } else {
            $options['idAlias'] = '';
        }
    
        if (array_key_exists('minDepth', $options)) {
            if (null !== $options['minDepth']) {
                $options['minDepth'] = (int) $options['minDepth'];
            }
        } else {
            $options['minDepth'] = $this->getMinDepth();
        }
    
        if ($options['minDepth'] < 0 || $options['minDepth'] === null) {
            $options['minDepth'] = 0;
        }
    
        if (array_key_exists('maxDepth', $options)) {
            if (null !== $options['maxDepth']) {
                $options['maxDepth'] = (int) $options['maxDepth'];
            }
        } else {
            $options['maxDepth'] = $this->getMaxDepth();
        }
    
        if (!isset($options['onlyActiveBranch'])) {
            $options['onlyActiveBranch'] = $this->getOnlyActiveBranch();
        }
    
        if (!isset($options['renderParents'])) {
            $options['renderParents'] = $this->getRenderParents();
        }
    
        return $options;
    }
    
     /**
     * Renders the deepest active menu within [$minDepth, $maxDeth], (called
     * from {@link renderMenu()})
     *
     * @param  Zend_Navigation_Container $container  container to render
     * @param  array                     $active     active page and depth
     * @param  string                    $ulClass    CSS class for first UL
     * @param  string                    $indent     initial indentation
     * @param  int|null                  $minDepth   minimum depth
     * @param  int|null                  $maxDepth   maximum depth
     * @return string                                rendered menu
     */
    protected function _renderDeepestMenu(Zend_Navigation_Container $container,
                                          $ulClass,
                                          $indent,
                                          $minDepth,
                                          $maxDepth)
    {
        if (!$active = $this->findActive($container, $minDepth - 1, $maxDepth)) {
            return '';
        }
    
        // special case if active page is one below minDepth
        if ($active['depth'] < $minDepth) {
            if (!$active['page']->hasPages()) {
                return '';
            }
        } else if (!$active['page']->hasPages()) {
            // found pages has no children; render siblings
            $active['page'] = $active['page']->getParent();
        } else if (is_int($maxDepth) && $active['depth'] +1 > $maxDepth) {
            // children are below max depth; render siblings
            $active['page'] = $active['page']->getParent();
        }
    
        $ulClass = $ulClass ? ' class="' . $ulClass . '"' : '';
        $html = $indent . '<ul' . $ulClass . '>' . self::EOL;
    
        $liRole = (! empty($this->getLiRole())) ? "role=\"{$this->getLiRole()}\"" : "";
    
        foreach ($active['page'] as $subPage) {
            if (!$this->accept($subPage)) {
                continue;
            }
            $liClass = $subPage->isActive(true) ? ' class="active"' : '';
            $html .= $indent . '    <li' . $liClass . ' ' . $liRole . '>' . self::EOL;
            $html .= $indent . '        ' . $this->htmlify($subPage) . self::EOL;
            $html .= $indent . '    </li>' . self::EOL;
        }
    
        $html .= $indent . '</ul>';
    
        return $html;
    }
    
    /**
     * Renders a normal menu (called from {@link renderMenu()})
     *
     * @param  Zend_Navigation_Container $container   container to render
     * @param  string                    $ulClass     CSS class for first UL
     * @param  string                    $indent      initial indentation
     * @param  int|null                  $minDepth    minimum depth
     * @param  int|null                  $maxDepth    maximum depth
     * @param  bool                      $onlyActive  render only active branch?
     * @return string
     */
    protected function _renderMenu(Zend_Navigation_Container $container,
                                   $ulClass,
                                   $indent,
                                   $minDepth,
                                   $maxDepth,
                                   $onlyActive)
    {
        $html = '';
    
        // find deepest active
        if ($found = $this->findActive($container, $minDepth, $maxDepth)) {
            $foundPage = $found['page'];
            $foundDepth = $found['depth'];
        } else {
            $foundPage = null;
        }
    
        // create iterator
        $iterator = new RecursiveIteratorIterator($container,
                            RecursiveIteratorIterator::SELF_FIRST);
        if (is_int($maxDepth)) {
            $iterator->setMaxDepth($maxDepth);
        }
    
        // iterate container
        $prevDepth = -1;
        foreach ($iterator as $page) {
            $depth = $iterator->getDepth();
            $isActive = $page->isActive(true);
            if ($depth < $minDepth || !$this->accept($page)) {
                // page is below minDepth or not accepted by acl/visibilty
                continue;
            } else if ($onlyActive && !$isActive) {
                // page is not active itself, but might be in the active branch
                $accept = false;
                if ($foundPage) {
                    if ($foundPage->hasPage($page)) {
                        // accept if page is a direct child of the active page
                        $accept = true;
                    } else if ($foundPage->getParent()->hasPage($page)) {
                        // page is a sibling of the active page...
                        if (!$foundPage->hasPages() ||
                            is_int($maxDepth) && $foundDepth + 1 > $maxDepth) {
                            // accept if active page has no children, or the
                            // children are too deep to be rendered
                            $accept = true;
                        }
                    }
                }
    
                if (!$accept) {
                    continue;
                }
            }
    
            $liRole = (! empty($this->getLiRole())) ? "role=\"{$this->getLiRole()}\"" : "";
    
    
            // make sure indentation is correct
            $depth -= $minDepth;
            $myIndent = $indent . str_repeat('        ', $depth);
    
            if ($depth > $prevDepth) {
                // start new ul tag
                if ($ulClass && $depth ==  0) {
                    $ulClass = ' class="' . $ulClass . '"';
                } else {
                    $ulClass = '';
                }
                $html .= $myIndent . '<ul' . $ulClass . '>' . self::EOL;
            } else if ($prevDepth > $depth) {
                // close li/ul tags until we're at current depth
                for ($i = $prevDepth; $i > $depth; $i--) {
                    $ind = $indent . str_repeat('        ', $i);
                    $html .= $ind . '    </li>' . self::EOL;
                    $html .= $ind . '</ul>' . self::EOL;
                }
                // close previous li tag
                $html .= $myIndent . '    </li>' . self::EOL;
            } else {
                // close previous li tag
                $html .= $myIndent . '    </li>' . self::EOL;
            }
    
            // render li tag and page
            $liClass = $isActive ? ' class="active"' : '';
            $html .= $myIndent . '    <li' . $liClass . ' ' . $liRole . '>' . self::EOL
                   . $myIndent . '        ' . $this->htmlify($page) . self::EOL;
    
            // store as previous depth for next iteration
            $prevDepth = $depth;
        }
    
        if ($html) {
            // done iterating container; close open ul/li tags
            for ($i = $prevDepth+1; $i > 0; $i--) {
                $myIndent = $indent . str_repeat('        ', $i-1);
                $html .= $myIndent . '    </li>' . self::EOL
                       . $myIndent . '</ul>' . self::EOL;
            }
            $html = rtrim($html, self::EOL);
        }
    
        return $html;
    }   
    
    class MyMenu扩展了Zend\u View\u Helper\u Navigation\u菜单
    {
    /**
    *想要一种在菜单li元素上设置aria角色的方法,因为它是
    *
    *@var字符串
    */
    受保护的$\u liRole='';
    /**
    *解决方法,这样我就可以在同一页上两次呈现这个该死的东西,而不会在页面上碰撞ID,然后看看接触点是什么,创建一个新的扩展类。实际上,只是新属性和一些字符串连接的“调整”来呈现标记

    我并没有在“第二级ul”中特别提到类,但传入一个附加属性将是微不足道的,并且遵循我所做的相同更改


    希望这能有所帮助。ZF 1.x显示了它的年龄,而这些视图助手从来没有那么好。底层的导航代码也不太糟糕,所以再次强调,也许可以从头开始编写自己的代码来渲染Zend Nav容器。祝你好运。

    这无疑是一个丑陋的黑客行为,但你可以通过处理
    public\n的输出来做到这一点v_main()
    带有正则表达式。因此,在
    header.php
    文件中,您将替换:

    echo public_nav_main();
    


    echo preg\u replace(“/(?我想你必须渲染部分视图脚本。你能确认问题与ZF 1.x有关吗?是的,它使用Zend 1.12.11。它实际上是Omeka的一部分,所以我将更新主要问题以指出这一点。感谢你的帮助性回答,我更新了我的主要问题,并提供了一些详细信息。理想情况下,我不想继续创建自定义z最终类,因为它到目前为止埋在底层结构中,如果他们更新它,它可能会被破坏。我想这可能是我唯一的选择,创建我自己的zend容器!今天晚些时候我会尝试查看您的更新。请注意,尽管ZF 1.x除了ZF 2.x之外,实际上没有其他地方可以更新,但一切都会更新不管怎么说,你评估过这个吗?这个网站似乎在使用它,而且看起来很有反应性:下行+:菜单标签不能有“ul”。所以,替换了“/?”?
    
    echo preg_replace( "/(?<!\/)ul(?!.*?nav)/", 'ul class="dropdown-menu"', public_nav_main() );