3

I am struggling with understanding how WordPress uses the Walker class. In particular, I don't understand the walk() method (I think).

First, let me explain what I understood:

When calling wp_nav_menu(), it's possible to add an array as argument, containing infos/options such as depth, container, theme location, walker to use and so on.

Inside wp_nav_menu(), these arguments are merged witch default values. The resulting array (later cast to object) called $args.

Inside wp_nav_menu(), walk_nav_menu_tree() is called, receiving $sorted_menu_items, $args->depth and $args as arguments.

Until that point I am able to understand what is happening, but inside walk_nav_menu_tree(), the Walker class is instantiated, and this is where I can't follow along anymore.

After instantiation, the walk() method of the Walker used is called.

According to its signature, walk() accepts two arguments: $elements and $max_depth.

But in walk_nav_menu_tree(), walk() gets passed only one argument called $args, which is an array containing the arguments passed to walk_nav_menu_tree(), which are actually $items(= $sorted_menu_items), $depth (= $args->depth), $r (= $args).

As if this isn't confusing enough already, at the beginning of the walk() method, there is this line:

$args = array_slice(func_get_args(), 2);

What happens here is using func_get_args(), all arguments passed to the method are gathered into an array, from which then the first two parts are omitted, which leaves us with $args only containing a the contents of a third argument that is not visible in the method signature.

Now, how can this work at all – as I pointed out walk() is called only with one argument, so how can $elements and $max_depth be left out, without resulting in an error?

  • It's called with call_user_func_array, so the 1st 2 elements get assigned to the declared arguments $elements and $max_depth, leaving the third element ($r which is the original $args) to be assigned via array_slice to $args. Simple! – bonger Dec 20 '14 at 12:49
  • @bonger as an answer please :) – Rarst Dec 20 '14 at 15:50
2

Per comments, it's called with call_user_func_array, so the 1st 2 elements get assigned to the declared arguments $elements and $max_depth, leaving the third element ($r which is the original $args) to be assigned via array_slice to $args. Eg

function wpse172812( $elements, $max_depth ) {
    $args = array_slice(func_get_args(), 2);
    error_log("elements=$elements, max_depth=$max_depth, args=" . print_r( $args, true ));
    // elements=arg1, max_depth=arg2,
    // args=Array ( [0] => Array ( [menu] => my_id [menu_class] => my_class ) )
}
$args = array( 'arg1', 'arg2', array( 'menu' => 'my_id', 'menu_class' => 'my_class' ) );
call_user_func_array( 'wpse172812', $args );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.