如何更改主题标题以支持多个导航菜单?

时间:2013-02-09 作者:user27251

我会尽量简短。。。。

我有一个只支持一个导航菜单的主题。此时,我想再添加2到3个菜单。我已成功在函数中注册菜单。php带有register\\u nav\\u菜单,我可以切换标题。在我的不同菜单之间手动编写php代码。

我的问题。。。由于我的主题使用一个标题(header.php),我无法在不更改所有其他页面导航菜单的情况下分配我的页面或发布我想要的导航菜单。

有人能帮我吗?提前谢谢。格雷格

1 个回复
最合适的回答,由SO网友:chrisguitarguy 整理而成

首先,关于导航菜单,您应该了解一些事情:

菜单只是一种分类法中的术语,称为nav_menu.

这样一来,任务就相当简单了:在编辑屏幕上放置一个自定义元框,显示选择导航菜单的选项。在前端,将导航菜单切换到您在管理区域中设置的任何菜单。唯一需要担心的是theme_location 价值在于主题对wp_nav_menu. 您想在哪里切换菜单?

这是一个示例,它将使用主题位置primary.

一个将所有内容总结为以下内容的电话:

<?php
class PerPostNavMenu
{
    const NONCE = \'wpse85243_nav_nonce\';
    const FIELD = \'_wpse85243_per_post_menu\';
    const LOC   = \'primary\'; // the location for twenty twelve

    private static $ins = null;

    public static function instance()
    {
        if (is_null(self::$ins)) {
            self::$ins = new self;
        }

        return self::$ins;
    }

    public static function init()
    {
        add_action(\'plugins_loaded\', array(self::instance(), \'_setup\'));
    }

    public function _setup()
    {
        // we\'ll add actions/filters here later
    }
}
现在,让我们添加元框。由于这篇文章在很多地方都有详细的介绍,我将给出悬崖笔记的解释:钩住add_meta_boxes, 呼叫add_meta_box. 在元框回调函数中,输出一个nonce和字段。

要保存这些值,请挂接到save_post, 检查以确保我们处于想要的位置(无自动保存,nonce验证),并且当前用户可以使用(update|delete)_post_meta.

<?php
class PerPostNavMenu
{
    const NONCE = \'wpse85243_nav_nonce\';
    const FIELD = \'_wpse85243_per_post_menu\';
    const LOC   = \'primary\'; // the location for twenty twelve

    // snip snip

    public function _setup()
    {
        add_action(\'add_meta_boxes\', array($this, \'addBox\'));
        add_action(\'save_post\', array($this, \'save\'), 10, 2);
    }

    public function addBox($post_type)
    {
        if (!post_type_exists($post_type)) {
            return;
        }

        add_meta_box(
            \'wpse85243_nav_menu\',
            __(\'Nav Menu\', \'wpse\'),
            array($this, \'boxCallback\'),
            $post_type,
            \'side\',
            \'low\'
        );
    }

    public function boxCallback($post)
    {
        $menu = get_post_meta($post->ID, static::FIELD, true);

        wp_nonce_field(static::NONCE . $post->ID, static::NONCE, false);

        printf(
            \'<label for="%s">%s</label>\',
            esc_attr(static::FIELD),
            esc_html__(\'Nav Menu\', \'wpse\')
        );

        echo \'<br />\';

        printf(\'<select name="%1$s" id="%1$s">\', esc_attr(static::FIELD));

        foreach ($this->getNavMenus() as $id => $name) {
            printf(
                \'<option value="%s" %s>%s</option>\',
                esc_attr($id),
                selected($menu, $id, false),
                esc_html($name)
            );
        }

        echo \'</select>\';
    }

    public function save($post_id, $post)
    {
        if (defined(\'DOING_AUTOSAVE\') && DOING_AUTOSAVE) {
            return;
        }

        if (
            !isset($_POST[static::NONCE]) ||
            !wp_verify_nonce($_POST[static::NONCE], static::NONCE . $post_id)
        ) {
            return;
        }

        $type = get_post_type_object($post->post_type);
        if (!current_user_can($type->cap->edit_post, $post_id)) {
            return;
        }

        $menu = isset($_POST[static::FIELD]) ? $_POST[static::FIELD] : false;

        if ($menu && \'-\' !== $menu) {
            update_post_meta($post_id, static::FIELD, absint($menu));
        } else {
            delete_post_meta($post_id, static::FIELD);
        }
    }

    private function getNavMenus()
    {
        $terms = get_terms(\'nav_menu\');

        $menus = array(\'-\' => __(\'Default\', \'wpse\'));
        if ($terms && !is_wp_error($terms)) {
            foreach($terms as $t) {
                $menus[$t->term_id] = $t->name;
            }
        }

        return apply_filters(\'per_post_nav_menus_list\', $menus);
    }
}
请注意用于检索导航菜单的助手方法。不多,只是一个方便的助手,可以通过过滤器运行结果。

最后,我们只需要关掉菜单。要做到这一点,请wp_nav_menu_args 而且,如果我们在一个单独的页面上,并且有正确的主题位置,请根据需要切换菜单。还包括一些额外的过滤器,使其更具可扩展性。

<?php
class PerPostNavMenu
{
    const NONCE = \'wpse85243_nav_nonce\';
    const FIELD = \'_wpse85243_per_post_menu\';
    const LOC   = \'primary\'; // the location for twenty twelve

    // snip snip

    public function _setup()
    {
        add_action(\'add_meta_boxes\', array($this, \'addBox\'));
        add_action(\'save_post\', array($this, \'save\'), 10, 2);
        add_filter(\'wp_nav_menu_args\', array($this, \'switchMenu\'));
    }

    // snip snip

    public function switchMenu($args)
    {
        // we can only deal with singular pages
        if (!is_singular()) {
            return;
        }

        $switch = apply_filters(
            \'per_post_nav_menus_switch\',
            isset($args[\'theme_location\']) && static::LOC === $args[\'theme_location\'],
            $args
        );

        // if we\'re allowed to switch, the the `menu` argument to
        // the correct menu ID.
        if ($switch) {
            $menu = get_post_meta(get_queried_object_id(), static::FIELD, true);

            if (\'-\' !== $menu) {
                $args[\'menu\'] = absint($menu);
            }
        }

        return $args;
    }

    // snip snip
}
以上所有内容as a plugin.

结束

相关推荐

WooCommerce dynamic menus

我有一个基本的WordPress网站,设置了Suffusion主题和WooCommerce插件。这在大多数情况下都很有效,但是当我让人们点击/悬停在“Shop”菜单图标上时,我希望它能够动态地下拉我定义的产品类别。我如何做到这一点?我肯定有关于这个主题的文档,但我不确定要查找什么。我主要是一名系统管理员。