Skip to content

Instantly share code, notes, and snippets.

@rohmann
Last active December 12, 2016 23:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rohmann/23e7b49f4b785ac8702b72889025a4a9 to your computer and use it in GitHub Desktop.
Save rohmann/23e7b49f4b785ac8702b72889025a4a9 to your computer and use it in GitHub Desktop.
WordPress Custom Nav walker as a template
<?php
/*
I've not tested it, but this is the result of thinking through how one might output custom navigation menu markup using a theme template file.
1. Include this class
2. Call a menu in one of your templates, and reference a template using the new arguments available. For example
wp_nav_menu( array(
'theme_location' => 'primary',
'walker' => new Custom_Template_Nav_Walker,
'start_el_template' => 'nav-item'
) );
3. Have a template called {$start_el_template}.php in your theme folder. For example "your-theme/nav-item.php"
In the template, use $el_data to shape any opening markup you like as a template
$class = empty($el_data['classes']) ? '' : class="' . esc_attr( join( ' ', $el_data['classes'] ) );
echo "<li $id $class"><a href="">
*/
class Custom_Template_Nav_Walker extends Walker_Nav_Menu {
/**
* Override these to quickly set static markup when not loading a custom template
*/
public $default_start_lvl = '<ul class="sub-menu">';
public $default_end_lvl = '</ul>';
public $default_end_el = '</li>';
/**
* You can override this to use your own view loading system. By default this
* will mimic get_template_part, but allow $el_data to be accessible in that file.
* @param string $_template_name Name of a template passed through custom arguments
* For example 'start_lvl_template' => 'my-custom-li'
* @param array $el_data Combination of attributes, content, and arguments
* @return string Should return a string opening <li> tag
*/
public function custom_template_loader( $template_name, $el_data ) {
$template = locate_template( array( $template_name ), false, false );
global $posts, $post, $wp_did_header, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID; // 01
if ( is_array( $wp_query->query_vars ) ) {
extract( $wp_query->query_vars, EXTR_SKIP );
}
if ( isset( $s ) ) {
$s = esc_attr( $s );
}
ob_start();
include( $_template_file );
return ob_get_clean();
}
/**
* Outputs the WordPress standard start_el markup. You can override this,
* but ideally you'd just override custom_template_loader and pass a template.
* @param array $data Combination of attributes, content, and arguments
* @return string WordPress default <li> element for this nav item
*/
public function default_start_el( $data ) {
$class_names = join( ' ', $data['classes'] );
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
$id = $data['id'] ? ' id="' . esc_attr( $data['id'] ) . '"' : '';
$output .= $indent . '<li' . $id . $class_names .'>';
$attributes = '';
foreach ( $data['atts'] as $attr => $value ) {
if ( ! empty( $value ) ) {
$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
$attributes .= ' ' . $attr . '="' . $value . '"';
}
}
$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';
$item_output .= $args->link_before . $data['title'] . $args->link_after;
$item_output .= '</a>';
$item_output .= $args->after;
return $item_output;
}
public function start_lvl( &$output, $depth = 0, $args = array() ) {
if ( $args['start_lvl_template'] ) {
$output .= $this->custom_template_loader( $args['start_lvl_template'], array(
'args' => $args,
'depth' => $depth
) );
} else {
$output .= $this->default_start_lvl;
}
}
public function end_lvl( &$output, $depth = 0, $args = array() ) {
if ( $args['end_lvl_template'] ) {
$output .= $this->custom_template_loader( $args['end_lvl_template'], array(
'args' => $args,
'depth' => $depth
) );
} else {
$output .= $this->default_end_lvl;
}
}
public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = 'menu-item-' . $item->ID;
$atts = array();
$atts['title'] = ! empty( $item->attr_title ) ? $item->attr_title : '';
$atts['target'] = ! empty( $item->target ) ? $item->target : '';
$atts['rel'] = ! empty( $item->xfn ) ? $item->xfn : '';
$atts['href'] = ! empty( $item->url ) ? $item->url : '';
$data = array(
'args' => apply_filters( 'nav_menu_item_args', $args, $item, $depth ),
'id' => apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args, $depth ),
'classes' => apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args, $depth ),
'atts' => apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth ),
'title' => apply_filters( 'nav_menu_item_title', apply_filters( 'the_title', $item->title, $item->ID ), $item, $args, $depth ),
'item' => $item,
);
$item_output = isset( $args['start_el_template'] ) ? $this->custom_template_loader( $template, $data ) : $this->default_start_el( $data );
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
public function end_el( &$output, $item, $depth = 0, $args = array() ) {
if ( $args['end_el_template'] ) {
$output .= $this->custom_template_loader( $args['end_el_template'], array(
'args' => $args,
'depth' => $depth
) );
} else {
$output .= $this->default_end_el;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment