To see how such a list can be created look at the code in wp-admin/includes/nav-menu.php
. Unfortunately, it is hard coded there, so you have to re-create the code.
First, let’s create two menus:
We can get these menus in PHP with wp_get_nav_menus()
(a wrapper for get_terms()
):
$menus = wp_get_nav_menus();
print '<pre>' . htmlspecialchars( print_r( $menus, TRUE ) ) . '</pre>';
Output:
Array
(
[0] => stdClass Object
(
[term_id] => 5
[name] => Paradigmatic Inconvenience
[slug] => paradigmatic-inconvenience
[term_group] => 0
[term_taxonomy_id] => 5
[taxonomy] => nav_menu
[description] =>
[parent] => 0
[count] => 0
)
[1] => stdClass Object
(
[term_id] => 6
[name] => Paul
[slug] => paul
[term_group] => 0
[term_taxonomy_id] => 6
[taxonomy] => nav_menu
[description] =>
[parent] => 0
[count] => 0
)
)
Now we build the selector function:
/**
* Build a dropdown selector for all existing nav menus.
*
* @author Thomas Scholz, toscho.de
* @param string $name Used as name attribute for the select element.
* @param string $selected Slug of the selected menu
* @param bool $print Print output or just return the HTML.
* @return string
*/
function t5_nav_menu_drop_down( $name, $selected = '', $print = TRUE )
{
// array of menu objects
$menus = wp_get_nav_menus();
$out = '';
// No menu found.
if ( empty ( $menus ) or is_a( $menus, 'WP_Error' ) )
{
// Give some feedback …
$out .= __( 'There are no menus.', 't5_nav_menu_per_post' );
// … and make it usable …
if ( current_user_can( 'edit_theme_options' ) )
{
$out .= sprintf(
__( ' <a href="%s">Create one</a>.', 't5_nav_menu_per_post' ),
admin_url( 'nav-menus.php' )
);
}
// … and stop.
$print and print $out;
return $out;
}
// Set name and ID to let you use a <label for='id_$name'>
$out = "<select name='$name' id='id_$name'>\n";
foreach ( $menus as $menu )
{
// Preselect the active menu
$active = $selected == $menu->slug ? 'selected' : '';
// Show the description
$title = empty ( $menu->description ) ? '' : esc_attr( $menu->description );
$out .= "\t<option value='$menu->slug' $active $title>$menu->name</option>\n";
}
$out .= '</select>';
$print and print $out;
return $out;
}
Calling this function …
t5_nav_menu_drop_down( 'my_nav_select', 'paul' );
… will give us a nice, simple select element with 'paul'
pre-selected:
Now we need a meta box to offer the selector to our post authors. To keep this short, I just use a child class of my Basic Meta Box. Basically, you call the function in the meta box and save the menu slug as post meta.
Then you can access the selected nav menu slug in your theme per:
get_post_meta( get_the_ID(), '_t5_nav_menu_per_post', TRUE );
Another way to get the full nav menu in your theme:
// Print a wp_nav_menu
do_action(
't5_custom_nav_menu',
// an array of wp_nav_menu() arguments.
array (
'menu' => 'default-menu',
// you may set a custom post ID
'post_id' => get_the_ID()
)
);
Because I like your idea very much I’ve added a theme helper function and mangled everything into a plugin. Get it on GitHub: T5 Nav Menu Per Post.
Oh, and welcome to WordPress Stack Exchange. Don’t worry about your English as long as you ask – and answer – interesting questions. :)
Update
To use the plugin with a custom post type like your portfolio
just install the plugin, activate it and add the following code to the file where you register the custom post type:
add_filter( 't5_nav_menu_per_post_post_types', 'wpse41695_add_post_type' );
function wpse41695_add_post_type( $post_types )
{
$post_types[] = 'portfolios';
return $post_types;
}
Your code still has many problems: global variables, missing prefixes, weird indentation. Recommended reading: Coding Standards and prefix everything.