2
votes

I am working with the walker class to create a menu for a WordPress theme and the code I have is;

class Walker_Nav_Primary extends Walker_Nav_menu {

    function start_lvl( &$output, $depth = 0, $args = array() ){ //ul
        $indent = str_repeat("\t",$depth);
        $submenu = ($depth > 0) ? ' sub-menu' : '';
        $output .= "\n$indent<ul class=\"dropdown-menu$submenu depth_$depth\">\n";
    }

    function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ){ //li a span

        $indent = ( $depth ) ? str_repeat("\t",$depth) : '';

        $li_attributes = '';
        $class_names = $value = '';

        $classes = empty( $item->classes ) ? array() : (array) $item->classes;

        $classes[] = ($args->walker->has_children) ? 'dropdown' : '';
        $classes[] = ($item->current || $item->current_item_ancestor) ? 'active' : '';
        $classes[] = 'menu-item-' . $item->ID;
        if( $depth && $args->walker->has_children ){
            $classes[] = 'dropdown-submenu';
        }

        $class_names =  join(' ', apply_filters('nav_menu_css_class', array_filter( $classes ), $item, $args ) );
        $class_names = ' class="' . esc_attr($class_names) . '"';

        $id = apply_filters('nav_menu_item_id', 'menu-item-'.$item->ID, $item, $args);
        $id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';

        $output .= $indent . '<li' . $id . $value . $class_names . $li_attributes . '>';

        $attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr($item->attr_title) . '"' : '';
        $attributes .= ! empty( $item->target ) ? ' target="' . esc_attr($item->target) . '"' : '';
        $attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr($item->xfn) . '"' : '';
        $attributes .= ! empty( $item->url ) ? ' href="' . esc_attr($item->url) . '"' : '';

        $attributes .= ( $args->walker->has_children ) ? ' class="dropdown-toggle" data-toggle="dropdown"' : '';

        $item_output = $args->before;
        $item_output .= '<a' . $attributes . '>';
        $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
        $item_output .= ( $depth == 0 && $args->walker->has_children ) ? ' <b class="caret"></b></a>' : '</a>';
        $item_output .= $args->after;

        $output .= apply_filters ( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );

    }

}

However, when a friend viewed the theme he was seeing the message below, I and no one else saw this message, and the menu works fine.

Strict standards: Declaration of Walker_Nav_Primary::start_lvl() should be compatible with Walker_Nav_Menu::start_lvl(&$output,$depth = 0, $args = Array) in .../inc/walker.php on line 0

So he made a couple of changes the first was to address this error by putting in $args =array() in the start_lvl function which as missing, but then he writes that $args is not an object its a array so you can't do $args->something, you have to do $args['something'], which gives the code;

class Walker_Nav_Primary extends Walker_Nav_menu {

    function start_lvl( &$output, $depth = 0, $args = array() ) { //ul
        $indent = str_repeat("\t",$depth);
        $submenu = ($depth > 0) ? ' sub-menu' : '';
        $output .= "\n$indent<ul class=\"dropdown-menu$submenu depth_$depth\">\n";
    }

    function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ){ //li a span
        $indent = ( $depth ) ? str_repeat("\t",$depth) : '';
        $li_attributes = '';
        $class_names = $value = '';
        $classes = empty( $item->classes ) ? array() : (array) $item->classes;

        $classes[] = ($args['walker']->has_children) ? 'dropdown' : '';

        $classes[] = ($item->current || $item->current_item_ancestor) ? 'active' : '';
        $classes[] = 'menu-item-' . $item->ID;
        if( $depth && $args['walker']->has_children ){
            $classes[] = 'dropdown-submenu';
        }
        $class_names =  join(' ', apply_filters('nav_menu_css_class', array_filter( $classes ), $item, $args ) );
        $class_names = ' class="' . esc_attr($class_names) . '"';
        $id = apply_filters('nav_menu_item_id', 'menu-item-'.$item->ID, $item, $args);
        $id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';
        $output .= $indent . '<li' . $id . $value . $class_names . $li_attributes . '>';
        $attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr($item->attr_title) . '"' : '';
        $attributes .= ! empty( $item->target ) ? ' target="' . esc_attr($item->target) . '"' : '';
        $attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr($item->xfn) . '"' : '';
        $attributes .= ! empty( $item->url ) ? ' href="' . esc_attr($item->url) . '"' : '';
        $attributes .= ( $args['walker']->has_children ) ? ' class="dropdown-toggle" data-toggle="dropdown"' : '';
        $item_output = $args['before'];
        $item_output .= '<a' . $attributes . '>';
        $item_output .= $args['link_before'] . apply_filters( 'the_title', $item->title, $item->ID ) . $args['link_after'];
        $item_output .= ( $depth == 0 && $args['walker']->has_children ) ? ' <b class="caret"></b></a>' : '</a>';
        $item_output .= $args['after'];
        $output .= apply_filters ( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    }
}

However, when I run the code I get the following error

Fatal error: Cannot use object of type stdClass as array in

referring to lines where

$classes[] = ($args->walker->has_children) ? 'dropdown' : '';

has been changed to

$classes[] = ($args['walker']->has_children) ? 'dropdown' : '';

We are both on the same PHP and WordPress so I don't understand why it is working for him and not me, and which is the correct method.

Can anyone shed any light?

1
OK firstly you have to be sure is $args array or object ? or it is inconsistent and then you have to be sure is there any key or property named as walker then you should check if the key or property is an object or not. I will make an answer to give you best usage but you have to be sure is $args array or object.FZE

1 Answers

0
votes

If you are sure $args is an array place this code before the use of $args

if (!isset($args['walker']) || !(is_object($args['walker']) && isset($args['walker']->has_children)) {
   $classes[] = '';
   $args = (object) array('walker' => array('has_children' => false));
}

But if the $args an object then use following :

if (!isset($args->walker) || !(is_object($args->walker) && isset($args->walker->has_children)) {
   $classes[] = '';
   $args = (object) array('walker' => array('has_children' => false));
}

If it is inconsistent firstly make this consistent, be sure $args array or object.