个性化阅读
专注于IT技术分析

用Timber添加多级菜单

我对Timber并不熟悉-实际上这是我第一次听说它, 但是我正在帮助一个慈善机构, 谁是Web开发人员让他们陷入困境。

我已经完成了大部分工作-除了使子菜单正常工作之外。

将项目添加到Wordpress中的子菜单位置时, 它们将显示在主菜单的同一级别上。

想知道是否有人可以帮助我?

下面是各种”细枝”的代码-但是让我知道你是否也需要函数代码来提供帮助。

menu.twig:

    {% for item in menu %}
        <li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
                <a class="{{ prefix }}__a" target="{{ item.target }}" href="{{ item.link }}"><span>{{ item.title }}</span></a>
                {% include "menu.twig" with {'menu': item.get_children} %}
        </li>
    {% endfor %}
{% endif %}

头文件

<header class="header">
    <div class="header__secondary">
        <div class="container">
            <div class="row">
                <div class="col-xs-12">
                    <nav class="header__nav nav-secondary">
                        <ul class="nav-secondary__ul">
                            {% include "menu.twig" with {
                                'menu': menu.header_secondary.items, 'prefix': 'nav-secondary'
                            } %}
                            <li class="nav-secondary__li nav-secondary__li--cart">
                                <a class="nav-secondary__a cart-customlocation" href="{{ cart_url }}"></a>
                            </li>
                        </ul>
                    </nav>
                </div>
            </div>
        </div>
    </div>
    <div class="header__primary">
        {% block header %}
            <div class="container">
                <div class="row">
                    <div class="col-xs-6 col-md-2">
                        <a href="/" class="header__logo">
                            <img src="{{ site.theme.link }}/dist/img/logo.jpg" alt="{{ site.name }} Logo">
                        </a>
                    </div>
                    <div class="col-xs-6 col-md-10">
                        <nav class="header__nav nav" role="navigation">
                            <ul class="nav__ul">
                                {% include "menu.twig" with {
                                    'menu': menu.header_primary.items, 'prefix': 'nav'
                                } %}
                            </ul>
                        </nav>
                        <div class="hamburger hamburger--spring">
                            <div class="hamburger-box">
                                <div class="hamburger-inner"></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        {% endblock %}
    </div>
</header>

functions.php

<?php
/**
 * Timber starter-theme
 * https://github.com/timber/starter-theme
 *
 * @package  WordPress
 * @subpackage  Timber
 * @since   Timber 0.1
 */

if ( ! class_exists( 'Timber' ) ) {
    add_action( 'admin_notices', function() {
        echo '<div class="error"><p>Timber not activated. Make sure you activate the plugin in <a href="' . esc_url( admin_url( 'plugins.php#timber' ) ) . '">' . esc_url( admin_url( 'plugins.php' ) ) . '</a></p></div>';
    });

    add_filter('template_include', function( $template ) {
        return get_stylesheet_directory() . '/static/no-timber.html';
    });

    return;
}

Timber::$dirname = array('views');
Timber::$autoescape = false;


/**
 * We're going to configure our theme inside of a subclass of Timber\Site
 * You can move this to its own file and include here via php's include("MySite.php")
 */
class StarterSite extends Timber\Site {
    /** Add timber support. */
    public function __construct() {
        add_action( 'after_setup_theme', array( $this, 'theme_supports' ) );
        add_filter( 'timber_context', array( $this, 'add_to_context' ) );
        add_filter( 'get_twig', array( $this, 'add_to_twig' ) );
        add_action( 'init', array( $this, 'register_post_types' ) );
        add_action( 'init', array( $this, 'register_taxonomies' ) );

        add_action( 'wp_enqueue_scripts', [$this, 'load_scripts'] );
        parent::__construct();

        register_nav_menu('header-secondary', 'Header Secondary');
        register_nav_menu('header-primary', 'Header Primary');

        remove_action('woocommerce_before_main_content', 'woocommerce_breadcrumb', 20, 0); // kill woo breadcrumbs
        remove_action( 'woocommerce_before_shop_loop' , 'woocommerce_catalog_ordering', 30 ); // kill woo sorting
        remove_action( 'woocommerce_before_shop_loop' , 'woocommerce_result_count', 20 ); // kill woo # results
        add_filter( 'woocommerce_add_to_cart_fragments', [$this, 'woocommerce_header_add_to_cart_fragment']);

        add_filter( 'woocommerce_get_image_size_gallery_thumbnail', function( $size ) {
            return array(
            'width' => 400, 'height' => 400, 'crop' => 0, );
        });


        add_action( 'after_setup_theme', function() {
            add_theme_support( 'woocommerce' );
        } );
    }

    /** This is where you can register custom post types. */
    public function register_post_types() {

        $name = "adoption";
        $singular = "Adoption";
        $plural = "Adoptions";

        $labels = array(
            'name' => _x("$plural", 'en'), 'singular_name' => _x("$singular", 'en'), 'all_items' => "All $plural", 'add_new' => _x("Add New $singular", 'en'), 'add_new_item' => _x("Add New $singular", 'en'), 'edit_item' => _x("Edit $singular", 'en'), 'new_item' => _x("New $singular", 'en'), 'view_item' => _x("View $singular", 'en'), 'search_items' => _x("Search $plural", 'en'), 'not_found' => _x("No $singular found", 'en'), 'not_found_in_trash' => _x("No $singular found in Trash", 'en'), 'parent_item_colon' => _x("Parent $singular:", 'en'), 'menu_name' => _x("$plural", 'en'), );

        $args = array(
            'labels' => $labels, 'hierarchical' => false, 'description' => $plural, 'supports' => array(
                'title', 'editor', 'thumbnail', 'revisions'
            ), 'taxonomies' => ['adoption_type'], 'public' => true, 'show_ui' => true, 'show_in_menu' => true, 'menu_position' => 4, 'menu_icon' => 'dashicons-welcome-view-site', 'show_in_nav_menus' => true, 'publicly_queryable' => true, 'exclude_from_search' => false, 'has_archive' => true, 'query_var' => true, 'can_export' => true, 'rewrite' => true, 'capability_type' => 'post'
        );

        register_post_type($name, $args);


        $name = "event";
        $singular = "Event";
        $plural = "Events";

        $labels = array(
            'name' => _x("$plural", 'en'), 'singular_name' => _x("$singular", 'en'), 'all_items' => "All $plural", 'add_new' => _x("Add New $singular", 'en'), 'add_new_item' => _x("Add New $singular", 'en'), 'edit_item' => _x("Edit $singular", 'en'), 'new_item' => _x("New $singular", 'en'), 'view_item' => _x("View $singular", 'en'), 'search_items' => _x("Search $plural", 'en'), 'not_found' => _x("No $singular found", 'en'), 'not_found_in_trash' => _x("No $singular found in Trash", 'en'), 'parent_item_colon' => _x("Parent $singular:", 'en'), 'menu_name' => _x("$plural", 'en'), );

        $args = array(
            'labels' => $labels, 'hierarchical' => false, 'description' => $plural, 'supports' => array(
                'title', 'editor', 'thumbnail', 'revisions'
            ), 'public' => true, 'show_ui' => true, 'show_in_menu' => true, 'menu_position' => 4, 'menu_icon' => 'dashicons-welcome-view-site', 'show_in_nav_menus' => true, 'publicly_queryable' => true, 'exclude_from_search' => false, 'has_archive' => true, 'query_var' => true, 'can_export' => true, 'rewrite' => true, 'capability_type' => 'post'
        );

        register_post_type($name, $args);

        if(function_exists('acf_add_options_page')) {
            acf_add_options_page([
                'page_title'    => 'Theme Content', 'menu_title'    => 'Theme Content', 'menu_slug'     => 'theme-content', 'capability'    => 'edit_posts', 'redirect'      => false
            ]);
        }

        if(function_exists('acf_add_options_page')) {
            acf_add_options_page([
                'page_title'    => 'Donation Settings', 'menu_title'    => 'Donation Settings', 'menu_slug'     => 'donation-settings', 'capability'    => 'edit_posts', 'redirect'      => false
            ]);
        }

    }
    /** This is where you can register custom taxonomies. */
    public function register_taxonomies() {

        $labels = array(
            'name'                       => 'Adoption Types', 'singular_name'              => 'Adoption Type', 'menu_name'                  => 'Adoption Type'
        );

        $rewrite = array(
            'slug'                       => 'adoptions', 'with_front'                 => true, 'hierarchical'               => false, );

        $args = array(
            'labels'                     => $labels, 'hierarchical'               => true, 'public'                     => true, 'show_ui'                    => true, 'show_admin_column'          => true, 'show_in_nav_menus'          => true, 'show_tagcloud'              => false, 'rewrite'                    => $rewrite, );

        register_taxonomy( 'adoption_type', 'adoption', $args );

    }

    public function load_scripts() {
        wp_enqueue_style( 'main', get_stylesheet_directory_uri() . '/dist/css/main.min.css' );
        wp_enqueue_script('slick-js', get_stylesheet_directory_uri() . '/dist/js/plugins/slick.min.js', 'jquery', false, true);
        wp_enqueue_script('main-js', get_stylesheet_directory_uri() . '/dist/js/main.js', ['jquery', 'slick-js'], false, true);
    }

    /** This is where you add some context
     *
     * @param string $context context['this'] Being the Twig's {{ this }}.
     */
    public function add_to_context( $context ) {

        $context['options'] = get_fields('options');

        $context['menu']['header_primary'] = new Timber\Menu('header-primary');
        $context['menu']['header_secondary'] = new Timber\Menu('header-secondary');

        $context['shop_url'] = get_permalink(woocommerce_get_page_id('shop' ));

        $context['site'] = $this;


        if (get_the_ID()) {
            // load page modules
            require_once('src/modules.php');
        }

        return $context;
    }

    public function theme_supports() {
        // Add default posts and comments RSS feed links to head.
        add_theme_support( 'automatic-feed-links' );

        /*
         * Let WordPress manage the document title.
         * By adding theme support, we declare that this theme does not use a
         * hard-coded <title> tag in the document head, and expect WordPress to
         * provide it for us.
         */
        add_theme_support( 'title-tag' );

        /*
         * Enable support for Post Thumbnails on posts and pages.
         *
         * @link https://developer.wordpress.org/themes/functionality/featured-images-post-thumbnails/
         */
        add_theme_support( 'post-thumbnails' );

        /*
         * Switch default core markup for search form, comment form, and comments
         * to output valid HTML5.
         */
        add_theme_support(
            'html5', array(
                'comment-form', 'comment-list', 'gallery', 'caption', )
        );

        /*
         * Enable support for Post Formats.
         *
         * See: https://codex.wordpress.org/Post_Formats
         */
        add_theme_support(
            'post-formats', array(
                'aside', 'image', 'video', 'quote', 'link', 'gallery', 'audio', )
        );

        add_theme_support( 'menus' );
    }

    /** This Would return 'foo bar!'.
     *
     * @param string $text being 'foo', then returned 'foo bar!'.
     */
    public function myfoo( $text ) {
        $text .= ' bar!';
        return $text;
    }

    /** This is where you can add your own functions to twig.
     *
     * @param string $twig get extension.
     */
    public function add_to_twig( $twig ) {
        $twig->addExtension( new Twig_Extension_StringLoader() );
        $twig->addFilter( new Twig_SimpleFilter( 'myfoo', array( $this, 'myfoo' ) ) );
        return $twig;
    }

    function woocommerce_header_add_to_cart_fragment( $fragments ) {
        global $woocommerce;

        ob_start();

        ?>
        <a class="cart-customlocation" href="<?php echo $woocommerce->cart->get_cart_url(); ?>" title="<?php _e('View your shopping cart', 'woothemes'); ?>"><?php echo sprintf(_n('%d item', '%d items', $woocommerce->cart->cart_contents_count, 'woothemes'), $woocommerce->cart->cart_contents_count);?> - <?php echo $woocommerce->cart->get_cart_total(); ?></a>
        <?php

        $fragments['a.cart-customlocation'] = ob_get_clean();

        return $fragments;
    }

}

new StarterSite();

编辑:根据收到的反馈, menu.twig代码如下-但是, 现在不显示任何菜单:

{% if items|default(menu.items) %}
<ul>
   {% for item in items|default(menu.items) %}
        <li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
            <a class="{{ prefix }}__a" target="{{ item.target }}" href="{{ item.link }}"><span>{{ item.title }}</span></a>
            {% include "menu.twig" with {'menu': item.get_children} %}
        </li>
    {% endfor %}
</ul>
{% endif %}

编辑2:下面是header.twig, 因为那里还有更多菜单项…

<header class="header">
    <div class="header__secondary">
        <div class="container">
            <div class="row">
                <div class="col-xs-12">
                    <nav class="header__nav nav-secondary">
                        <ul class="nav-secondary__ul">
                            {% include "menu.twig" with {
                                'menu': menu.menu_header_secondary.items, 'prefix': 'nav-secondary'
                            } %}
                            <li class="nav-secondary__li nav-secondary__li--cart">
                                <a class="nav-secondary__a cart-customlocation" href="{{ cart_url }}"></a>
                            </li>
                        </ul>
                    </nav>
                </div>
            </div>
        </div>
    </div>
    <div class="header__primary">
        {% block header %}
            <div class="container">
                <div class="row">
                    <div class="col-xs-6 col-md-2">
                        <a href="/" class="header__logo">
                            <img src="{{ site.theme.link }}/dist/img/logo.jpg" alt="{{ site.name }} Logo">
                        </a>
                    </div>
                    <div class="col-xs-6 col-md-10">
                        <nav class="header__nav nav" role="navigation">
                            <ul class="nav__ul">
                                {% include "menu.twig" with {
                                    'menu': menu.menu_header_primary.items, 'prefix': 'nav'
                                } %}
                            </ul>
                        </nav>
                        <div class="hamburger hamburger--spring">
                            <div class="hamburger-box">
                                <div class="hamburger-inner"></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        {% endblock %}
    </div>
</header>

编辑3-@Gchtr输入后的当前配置, 并获得正确的菜单以在正确的位置显示。仍然没有子菜单:

menu.twig:

{% set items = items|default(menu.items) %}

{% if items %}
<ul>
    {% for item in items %}
        <li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
            <a class="{{ prefix }}__a" target="{{ item.target }}" href="{{ item.link }}"><span>{{ item.title }}</span></a>
            {% if item.children %}
                {% include "menu.twig" with { items: item.children } %}
            {% endif %}
        </li>
    {% endfor %}
</ul>
{% endif %}

header.twig:

<header class="header">
    <div class="header__secondary">
        <div class="container">
            <div class="row">
                <div class="col-xs-12">
                    <nav class="header__nav nav-secondary">
                        <ul class="nav-secondary__ul">
                            {% include "menu.twig" with {
                                'menu': menu_header_secondary, 'prefix': 'nav-secondary'
                            } %}
                            <li class="nav-secondary__li nav-secondary__li--cart">
                                <a class="nav-secondary__a cart-customlocation" href="{{ cart_url }}"></a>
                            </li>
                        </ul>
                    </nav>
                </div>
            </div>
        </div>
    </div>
    <div class="header__primary">
        {% block header %}
            <div class="container">
                <div class="row">
                    <div class="col-xs-6 col-md-2">
                        <a href="/" class="header__logo">
                            <img src="{{ site.theme.link }}/dist/img/logo.jpg" alt="{{ site.name }} Logo">
                        </a>
                    </div>
                    <div class="col-xs-6 col-md-10">
                        <nav class="header__nav nav" role="navigation">
                            <ul class="nav__ul">
                                {% include "menu.twig" with {
                                    'menu': menu_header_primary, 'prefix': 'nav'
                                } %}
                            </ul>
                        </nav>
                        <div class="hamburger hamburger--spring">
                            <div class="hamburger-box">
                                <div class="hamburger-inner"></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        {% endblock %}
    </div>
</header>

functions.php(Header Stuff的片段, 而不是全部片段):

        public function add_to_context( $context ) {

        $context['options'] = get_fields('options');

                $context['menu_header_primary']   = new Timber\Menu( 'header-primary' );
                $context['menu_header_secondary'] = new Timber\Menu( 'header-secondary') ;

        $context['shop_url'] = get_permalink(woocommerce_get_page_id('shop' ));

                $context['site'] = $this;

#1


在add_to_context()方法的StarterSite类中, 你将像这样添加菜单:

$context['menu']['header_primary'] = new Timber\Menu('header-primary');
$context['menu']['header_secondary'] = new Timber\Menu('header-secondary');

现在, 当你想在Twig中使用access menu.items时, 此操作将无效, 因为你无法访问嵌套值。它应该是menu.header_primary.items。为了简化此操作, 我将其更改为使用单独的上下文条目:

$context['menu_header_primary']   = new Timber\Menu( 'header-primary' );
$context['menu_header_secondary'] = new Timber\Menu( 'header-secondary') ;

然后, 对于Twig文件, 你始终需要传递菜单变量。

{% set items = items|default(menu.items) %}

{% if items %}
<ul>
    {% for item in items %}
        <li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
            <a class="{{ prefix }}__a" target="{{ item.target }}" href="{{ item.link }}"><span>{{ item.title }}</span></a>
            {% if item.children %}
                {% include "menu.twig" with { items: item.children } %}
            {% endif %}
        </li>
    {% endfor %}
</ul>
{% endif %}

编辑

在header.twig中, 你还需要从菜单包含中删除嵌套(menu_header_primary.items, 而不是menu.menu_header_primary.items。否则, Timber将采用它可以找到的第一个菜单。

<nav class="header__nav nav" role="navigation">
    <ul class="nav__ul">
        {% include "menu.twig" with {
            menu: menu_header_primary, prefix: 'nav'
        } %}
    </ul>
</nav>

#2


好像你缺少<ul> </ ul>包装器, 或者你没有完整地发布代码:

{% if menu %}
    <ul>
    {% for item in menu %}
        <li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
            <a class="{{ prefix }}__a"  target="{{ item.target }}" href="{{ item.link }}">{{ item.title }}</a>
            {% include "menu.twig" with {'items': item.children} %}
        </li>
    {% endfor %}
    </ul>
{% endif %}
赞(0)
未经允许不得转载:srcmini » 用Timber添加多级菜单

评论 抢沙发

评论前必须登录!