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?
1 Answer
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 );