I use the following code to change the title of WordPress posts and pages. But it changes nav menu item titles too, which I want to avoid.
I want to change the title of posts and pages in: home page, all archive pages and all widgets (recent posts widget, random post widget, etc.)
There are similar questions in both Stack Overflow and WP Stack Exchange suggesting to use in_the_loop() function. Unfortunately, it doesn’t work for me, because if I place it, it also affects the sidebar widgets.
That means, if I use in_the_loop() function, the_title filter does not affect recent posts widget, random post widget etc.
So how can I apply the_title filter for just post and page titles, but not menu titles?
function pppp_title_update( $title, $id = null ) {
if ( ! is_admin() ) {
if(is_singular(array('post','page')) || is_archive() || is_home()){
if(in_the_loop()){
$current_post_id = get_the_ID();
$new_titile = get_post_meta($current_post_id, 'pp_new_title',true);
return $new_titile;
}
}
}
return $title;
}
add_filter( 'the_title', 'pppp_title_update', 10, 2 );
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Problem Description:
Let me rephrase the question first. You want to:
-
Set new title to all
postandpagetype from a meta field. - You want this to happen everywhere (home page, single page, widgets etc.)
- However, you don’t want this title change to happen if the title is on the Navigation Menu.
Solution:
Before I give you the CODE, let me explain a few points first (based on your CODE):
How to change titles of all posts and pages:
You already know the use of the_title filter. However, if you want to target all post and page type titles (but not custom post types), then your condition:
is_singular(array('post','page')) || is_archive() || is_home()
will not work. For example, it’ll change custom post type on an archive page or the home page as well. This condition doesn’t check if the title we are filtering is a page or post type. Instead, it checks if the page itself is either singular (post or page) or it’s an archive (category, tag etc.) page or the home page. So custom post types in these pages also gets affected. Additionally, if there is a widget in a custom post type (singular) page, then by this logic, page or post titles in that widget will not be affected there.
To fix that, we need a different check, like:
$post = get_post( $id ); if ( $post instanceof WP_Post && ( $post->post_type == 'post' || $post->post_type == 'page' ) )
WordPress applies the_title filter twice on the navigation menu items’ title (if the menu items correspond to existing posts or pages).
-
First as the corresponding post or page title. This happens in the
wp_setup_nav_menu_item()function ofwp-includes/nav-menu.phpfile. -
Then as the Menu item title itself. This happens in the
Walker_Nav_Menuclass.
For your requirement, we need to stop the the_title filter both the times.
Fortunately, WordPress has two filters: pre_wp_nav_menu fires before filtering menu titles and wp_nav_menu_items fires after filtering menu titles. So we can use these two filters to first remove the the_title filter for nav menu item titles and then add the the_title filter back again for other titles.
CODE
You may use the following CODE in the theme’s functions.php file or as a separate plugin:
function wpse309151_title_update( $title, $id = null ) {
if ( ! is_admin() && ! is_null( $id ) ) {
$post = get_post( $id );
if ( $post instanceof WP_Post && ( $post->post_type == 'post' || $post->post_type == 'page' ) ) {
$new_titile = get_post_meta( $id, 'pp_new_title', true );
if( ! empty( $new_titile ) ) {
return $new_titile;
}
}
}
return $title;
}
add_filter( 'the_title', 'wpse309151_title_update', 10, 2 );
function wpse309151_remove_title_filter_nav_menu( $nav_menu, $args ) {
// we are working with menu, so remove the title filter
remove_filter( 'the_title', 'wpse309151_title_update', 10, 2 );
return $nav_menu;
}
// this filter fires just before the nav menu item creation process
add_filter( 'pre_wp_nav_menu', 'wpse309151_remove_title_filter_nav_menu', 10, 2 );
function wpse309151_add_title_filter_non_menu( $items, $args ) {
// we are done working with menu, so add the title filter back
add_filter( 'the_title', 'wpse309151_title_update', 10, 2 );
return $items;
}
// this filter fires after nav menu item creation is done
add_filter( 'wp_nav_menu_items', 'wpse309151_add_title_filter_non_menu', 10, 2 );
Method 2
WordPress navigation editor has ability to change menu title regardless of the title of the post/page.
If you need more automated solution code below will replace title of the post/page everywhere using the_title filter but restore default title of the menu item using nav_menu_item_title filter.
/**
* Replace post/page title on home, single and archive pages.
*
* @param string $title Post title
* @param int $post_id Post ID
*
* @return string New post tilte
*/
function wpse_309151_get_replace_default_title_from_meta( $title, $post_id ) {
$post_type = get_post_type( $post_id );
if( !is_admin() && ( $post_type === 'post' || $post_type === 'page' ) ) {
$new_title = get_post_meta( $post_id, 'wpse_309151_post_title', true);
if( $new_title && !empty( $new_title ) ) {
return $new_title;
}
}
return $title;
}
add_filter( 'the_title', 'wpse_309151_get_replace_default_title_from_meta', 10, 2 );
/**
* Restore default post/page title in navigation
*
* @param string $title The menu item's title.
* @param WP_Post $item The current menu item.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $depth Depth of menu item. Used for padding.
*
* @return string Restored post title
*/
function wpse_309151_get_restore_default_title_for_navigation( $title, $item, $args, $depth ) {
// Remove filter to not affect title
remove_filter( 'the_title', 'wpse_309151_get_replace_default_title_from_meta', 10, 2 );
$post_id = $item->object_id;
$title = get_the_title( $post_id );
// Add the title filter back
add_filter( 'the_title', 'wpse_309151_get_replace_default_title_from_meta', 10, 2 );
return $title;
}
add_filter( 'nav_menu_item_title', 'wpse_309151_get_restore_default_title_for_navigation', 10, 4 );
Method 3
If you have the post object (get_the_ID(); or $post->ID; are essentially the same) See https://stackoverflow.com/questions/22351038/get-the-current-page-id-inside-wordpress-plugin-page, then you should also be able to do use either https://developer.wordpress.org/reference/functions/get_post_type/ to check the type or
if (in_array($post->post_type, array('post', 'page')) {
... swop the title
}
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0