2

After we save a post/page, a new menu item is created (with the same title) in the navigation that we have created in nav-menus.php.

If we need to change the menu item title, we need to go to nav-menus.php and change it to something else.

Is it possible to have some text field, for example in the edit post/page, where we can write the menu item title that we want for this page/post without needing to edit nav-menus.php each time?

This can really save a lot of time for users.

Here is the full and working code! Thanks to @Howdy_McGee

/**
 * Adds a box to the main column on the Page edit screens.
 */
function menu_item_title_changer_add_meta_box() {

    $screens = array( 'page' );

    foreach ( $screens as $screen ) {

        add_meta_box(
            'menu_item_title_changer',
            __( 'Menu item title changer', 'webic-admin' ),
            'menu_item_title_changer_callback',
            $screen
        );
    }
}
add_action( 'add_meta_boxes', 'menu_item_title_changer_add_meta_box' );

/**
 * Prints the box content.
 * 
 * @param WP_Post $post The object for the current post/page.
 */
function menu_item_title_changer_callback( $post ) {

    // Add a nonce field so we can check for it later.
    wp_nonce_field( 'menu_item_title_changer_meta_box', 'menu_item_title_changer_meta_box_nonce' );

    /*
     * Use get_post_meta() to retrieve an existing value
     * from the database and use the value for the form.
     */
    $value = get_post_meta( $post->ID, '_menu_item_title_changer', true );

    echo '<label for="menu_item_title_changer_field">';
    _e( 'Description for this field', 'myplugin_textdomain' );
    echo '</label> ';
    echo '<input type="text" id="menu_item_title_changer_field" name="menu_item_title_changer_field" value="' . esc_attr( $value ) . '" size="25" />';
}

/**
 * When the post is saved, saves our custom data.
 *
 * @param int $post_id The ID of the post being saved.
 */
function menu_item_title_changer_save_meta_box_data( $post_id, $post ) {

    /*
     * We need to verify this came from our screen and with proper authorization,
     * because the save_post action can be triggered at other times.
     */

    // Check if our nonce is set.
    if ( ! isset( $_POST['menu_item_title_changer_meta_box_nonce'] ) ) {
        return;
    }

    // Verify that the nonce is valid.
    if ( ! wp_verify_nonce( $_POST['menu_item_title_changer_meta_box_nonce'], 'menu_item_title_changer_meta_box' ) ) {
        return;
    }

    // If this is an autosave, our form has not been submitted, so we don't want to do anything.
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return;
    }

    // Check the user's permissions.
    if ( isset( $_POST['post_type'] ) && 'page' == $_POST['post_type'] ) {

        if ( ! current_user_can( 'edit_page', $post_id ) ) {
            return;
        }

    } else {

        if ( ! current_user_can( 'edit_post', $post_id ) ) {
            return;
        }
    }

    /* OK, it's safe for us to save the data now. */

    // Make sure that it is set.
    if ( ! isset( $_POST['menu_item_title_changer_field'] ) ) {
        return;
    }


    // here is the code here it is working bug my system stack after i click save "save"
    if( 'page' == $post->post_type ) {

        // Check Nonces

        $nav_item = new WP_Query( array(
            'post_type'      => 'nav_menu_item',        // Nav Post Type
            'posts_per_page' => 1,                      // We only expect 1 result, if any
            'meta_key'       => '_menu_item_object_id', // With our Meta Key
            'meta_value'     => $post->ID               // And our Correct Page
        ) );

        if( $nav_item->have_posts() ) {                 // Ensure something was found
            wp_update_post( array(                      // Update the `nav_menu_item` Post Title
                'ID'            => $nav_item->posts[0]->ID,
                'post_title'    => htmlspecialchars( sanitize_text_field( $_POST['menu_item_title_changer_field'] ) )
            ) );
        }

        // Update Page Meta
    }

    // Sanitize user input.
    $my_data = sanitize_text_field( $_POST['menu_item_title_changer_field'] );

    // Update the meta field in the database.
    update_post_meta( $post_id, '_menu_item_title_changer', $my_data );

}
add_action( 'save_post', 'menu_item_title_changer_save_meta_box_data', 10, 3 );
2
  • What have you tried so far? Have you tried creating a metabox? – Howdy_McGee May 1 '15 at 15:15
  • @Howdy_McGee i know how to create metabox this is not the problem here. but i dont know what to do next. how can i update by code the menu item title that connected to this page/post? – need-help May 1 '15 at 15:21
2

Whenever you add a new item to WordPress Menu ( Appearance -> Menu ) it creates a new Post of Post Type nav_menu_item and gets assigned a post meta called _menu_item_object_id with the main Post ID.

For example, if I create a page called "Home" it gets assigned a Post ID of 2. Now, when I go to Menus and add the page to a menu, WordPress creates a new post of post type nav_menu_item, assigns the title to "Home", gives it a ID in the database of 3 and assigns post meta _menu_item_object_id = 2. If we want to change the title to "Homepage" in Menus, it would change the Post ID 3 to title "Homepage".

If we wanted to change the title via metabox we would need to find Post Type nav_menu_item that has post_meta _menu_item_object_id with the same ID as our current page. I'm assuming you already have a metabox setup, are checking post types, and nonces.

if( 'page' == $post->post_type ) {

    // Check Nonces

    $nav_item = new WP_Query( array(
        'post_type'      => 'nav_menu_item',        // Nav Post Type
        'posts_per_page' => 1,                      // We only expect 1 result, if any
        'meta_key'       => '_menu_item_object_id', // With our Meta Key
        'meta_value'     => $post->ID               // And our Correct Page
    ) );

    if( $nav_item->have_posts() ) {                 // Ensure something was found
        wp_update_post( array(                      // Update the `nav_menu_item` Post Title
            'ID'            => $nav_item->posts[0]->ID,
            'post_title'    => htmlspecialchars( sanitize_text_field( $_POST['_textbox_name'] ) )
        ) );
    }

    // Update Page Meta
}

At the end of the above code, you would also want to update the Pages post meta to the new title so you can re-display it in the metabox textbox which makes it easier for the user to update in the future.


Alternatively, if you want to update the metabox textbox whenever a user adds a new Item to the Menu you can reverse the process:

if( 'nav_menu_item' == $post->post_type ) {
    // Check Nonces

    $added_id   = get_post_meta( $post->ID, '_menu_item_object_id', true ); // This may or may not be a Page ID
    $type       = get_post_field( 'post_type', $added_id );

    if( 'page' == $type ) {
        // Update Page Metabox Textbox Here with `$post->post_title`
    }
}
5
  • wow... thanks! @Howdy_McGee i will try this and let you know. – need-help May 1 '15 at 16:09
  • i have check the code and all works when i put the code in "save_post" action but this stack all the system. if i just put this code to functions.php nothing happens (the menu item title don't get updated). i missing something? – need-help May 1 '15 at 17:40
  • i have update the question with full code. with this code after i click "save" all stack but the menu item title get updated with the text field. – need-help May 1 '15 at 17:53
  • @need-help - The reason it's not working is because you're not passing the $post object to save_post hook - Developer Documentation. If you don't want to pass $post you need to change if( 'page' == $post->post_type ) to instead use $_POST['post_type'] and change any other instances of $post in my code. – Howdy_McGee May 1 '15 at 17:59
  • 1
    thanks i didn't see that. i have update my question with full working code! thanks! – need-help May 1 '15 at 18:11

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.