[Resolved] Creating a menu walker

Home Forums Support [Resolved] Creating a menu walker

Home Forums Support Creating a menu walker

  • This topic has 7 replies, 2 voices, and was last updated 4 years ago by Tom.
Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • #826192
    Anne Marie

    Hi there,

    I’m trying to customize the primary menu using a walker class and figured I’d start by copying GP’s own code and then revising it. I’ve copied the function generate_navigation_position from inc/structure/navigation.php into my child theme’s functions.php. I modified the call to wp_nav_menu() to refer to my walker class:

    
    wp_nav_menu(
       array(
          'theme_location' => 'primary',
          'container' => 'div',
          'container_class' => 'main-nav',
          'container_id' => 'primary-menu',
          'menu_class' => '',
          'fallback_cb' => 'generate_menu_fallback',
          'items_wrap' => '<ul id="%1$s" class="%2$s ' . join( ' ', generate_get_element_classes( 'menu' ) ) . '">%3$s</ul>',
          'walker' => new Generate_Page_Walker ( ), // NEW LINE.
       )
    ) ;
    

    Then I copied the GP walker class, Generate_Page_Walker, from inc/structure/navigation.php and pasted into my child theme’s functions.php.

    
    class Generate_Page_Walker extends Walker_Page {
    	function start_el( &$output, $page, $depth = 0, $args = array(), $current_page = 0 ) {
    		$css_class = array( 'page_item', 'page-item-' . $page->ID );
    		$button = '';
    
    		if ( isset( $args['pages_with_children'][ $page->ID ] ) ) {
    			$css_class[] = 'menu-item-has-children';
    			$button = '<span role="presentation" class="dropdown-menu-toggle"></span>';
    		}
    
    		if ( ! empty( $current_page ) ) {
    			$_current_page = get_post( $current_page );
    			if ( $_current_page && in_array( $page->ID, $_current_page->ancestors ) ) {
    				$css_class[] = 'current-menu-ancestor';
    			}
    			if ( $page->ID == $current_page ) {
    				$css_class[] = 'current-menu-item';
    			} elseif ( $_current_page && $page->ID == $_current_page->post_parent ) {
    				$css_class[] = 'current-menu-parent';
    			}
    		} elseif ( $page->ID == get_option( 'page_for_posts' ) ) {
    			$css_class[] = 'current-menu-parent';
    		}
    
    		$css_classes = implode( ' ', apply_filters( 'page_css_class', $css_class, $page, $depth, $args, $current_page ) );
    
    		$args['link_before'] = empty( $args['link_before'] ) ? '' : $args['link_before'];
    		$args['link_after'] = empty( $args['link_after'] ) ? '' : $args['link_after'];
    
    		$output .= sprintf(
    			'<li class="%1$s"><a href="%2$s">%3$s%4$s%5$s%6$s</a>',
    			$css_classes,
    			get_permalink( $page->ID ),
    			$args['link_before'],
    			apply_filters( 'the_title', $page->post_title, $page->ID ),
    			$args['link_after'],
    			$button
    		);
    	}
    }
    

    At this point I have only modified a single line of code: adding the reference to the walker class in wp_nav_menu(). When I try to view my website, the browser displays the following PHP error:

    Fatal error: Cannot use object of type stdClass as array in /Users/saul/Documents/apache_sites/pce.local/wp-content/themes/pce-theme/functions.php on line 139

    Line 139 corresponds to this line:

    
    if ( isset( $args['pages_with_children'][ $page->ID ] ) ) {
    

    It turns out that all references to $args trigger this PHP error. $args is an array, so I don’t see what the problem is.

    Can someone investigate what I might be doing wrong? I thought that executing the exact same code as the GP theme wouldn’t create any issues.

    Thank you!

    –Saul

    PS. I’ve provided a link to my website (a work-in-progress for a client) in this ticket, but it won’t show the error since I’ve disabled the offending code.

    GeneratePress 2.2.2
    GP Premium 1.7.8
    #826662
    Tom
    Lead Developer
    Lead Developer

    Hi there,

    What change did you make?

    I assume you change the walker class name to something unique to you?

    #826681
    Anne Marie

    Hi Tom,

    Thanks for your response. I made no change other than referencing the walker class in wp_nav_menu(). I did not change the class name to something unique; there’s a conditional in the GP theme that only defines the Generate_Page_Walker class if it doesn’t already exist, so I kept the same name. When I tried to change the name of my class to something else, the same PHP error persisted.

    And just in case you are curious, here is the var_dump() of the $args array:

    
    object(stdClass)#4279 (17) {
      ["menu"]=>
      object(WP_Term)#4282 (10) {
        ["term_id"]=>
        int(8)
        ["name"]=>
        string(18) "primary navigation"
        ["slug"]=>
        string(18) "primary-navigation"
        ["term_group"]=>
        int(0)
        ["term_taxonomy_id"]=>
        int(8)
        ["taxonomy"]=>
        string(8) "nav_menu"
        ["description"]=>
        string(0) ""
        ["parent"]=>
        int(0)
        ["count"]=>
        int(16)
        ["filter"]=>
        string(3) "raw"
      }
      ["container"]=>
      string(3) "div"
      ["container_class"]=>
      string(8) "main-nav"
      ["container_id"]=>
      string(12) "primary-menu"
      ["menu_class"]=>
      string(0) ""
      ["menu_id"]=>
      string(0) ""
      ["echo"]=>
      bool(true)
      ["fallback_cb"]=>
      string(22) "generate_menu_fallback"
      ["before"]=>
      string(0) ""
      ["after"]=>
      string(0) ""
      ["link_before"]=>
      string(0) ""
      ["link_after"]=>
      string(0) ""
      ["items_wrap"]=>
      string(49) "<ul id="%1$s" class="%2$s menu sf-menu">%3$s</ul>"
      ["item_spacing"]=>
      string(8) "preserve"
      ["depth"]=>
      int(0)
      ["walker"]=>
      object(Generate_Page_Walker)#4278 (4) {
        ["tree_type"]=>
        string(4) "page"
        ["db_fields"]=>
        array(2) {
          ["parent"]=>
          string(11) "post_parent"
          ["id"]=>
          string(2) "ID"
        }
        ["max_pages"]=>
        int(1)
        ["has_children"]=>
        bool(false)
      }
      ["theme_location"]=>
      string(7) "primary"
    }
    

    –Saul

    #827016
    Tom
    Lead Developer
    Lead Developer

    What’s the change you’re trying to make? There might be a more simple way.

    Let me know 🙂

    #827527
    Anne Marie

    Hi Tom,

    The change I’m trying to make is to create a custom layout for the primary navigation menu. I need to manipulate some of the links as well, since some “pages” will actually be subheadings in a mega menu. The menu will be dynamic in that when someone mouses over a link, an image and brief textual description will appear / change describing that link. I’ll need to add quite a bit of markup to make this happen. My thought was to start with the existing walker as a baseline and then customize it from there. But this PHP error is preventing that from happening.

    —Saul

    #827827
    Tom
    Lead Developer
    Lead Developer

    So what I would do is filter into the current menu and change the walker:

    add_filter( 'wp_nav_menu_args', function ( $args ) {
        if ( 'primary' === $args['theme_location'] ) {
            $args['walker'] = new Your_Custom_Walker_Class();
        }
    
        return $args;
    } );

    Then you can create your own walker with your own custom class name.

    This will avoid conflicts with the theme and you’ll be able to make any necessary changes in your walker class.

    #838230
    Anne Marie

    Tom,

    This did the trick. Thank you so much!

    –Saul

    #838255
    Tom
    Lead Developer
    Lead Developer
Viewing 8 posts - 1 through 8 (of 8 total)
  • You must be logged in to reply to this topic.