Примените фильтр заголовка() в заголовке публикации и страницы, но не в заголовке меню
Я использую следующий код для изменения названия записей WordPress и страниц . Но это также меняет названия пунктов навигационного меню, чего я хочу избежать.
Я хочу изменить название сообщений и страниц в: домашняя страница , все архивные страницы и все виджеты (виджет последних сообщений, виджет случайных сообщений и т.д.)
Существуют аналогичные вопросы как в Stack Overflow, так и в WP Stack Exchange, предлагающие использовать in_the_loop()
функция. К сожалению, это не работает для меня, потому что, если я размещу его, это также повлияет на виджеты боковой панели.
Это означает, что если я использую функцию in_the_loop()
, фильтр the_title
не влияет recent posts widget
, random post widget
и т.д.
Итак, как я могу применить фильтр the_title
только для заголовков post
и page
, но не для заголовков меню?
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 );
3 answers
Описание проблемы:
Позвольте мне сначала перефразировать вопрос. Вы хотите:
Установите новый заголовок для всех
post
иpage
типов из мета-поля.Вы хотите, чтобы это происходило везде (домашняя страница, отдельная страница, виджеты и т.Д.)
Однако вы не хотите, чтобы это изменение заголовка происходило, если заголовок находится в меню навигации.
Решение:
Прежде чем я дам вам КОД, позвольте мне объяснить несколько пункты первые (на основе вашего КОДА):
Как изменить названия всех сообщений и страниц:
Вы уже знаете, как использовать фильтр the_title
. Однако, если вы хотите настроить таргетинг на все заголовки типов post
и page
(но не на пользовательские типы записей), то ваше условие:
is_singular(array('post','page')) || is_archive() || is_home()
Не будет работать. Например, это изменит пользовательский тип записи на странице архива или на домашней странице. Это условие не проверяет, является ли заголовок, который мы фильтруем, типом page
или post
. Вместо этого он проверяет, является ли сама страница либо является единственной (post
или page
), либо это страница архива (категория, тег и т.д.) или домашняя страница. Таким образом, пользовательские типы записей на этих страницах также затрагиваются. Кроме того, если на странице пользовательского типа публикации (в единственном числе) есть виджет, то по этой логике заголовки page
или post
в этом виджете не будут затронуты.
Чтобы исправить это, нам нужна другая проверка, например:
$post = get_post( $id );
if ( $post instanceof WP_Post && ( $post->post_type == 'post' || $post->post_type == 'page' ) )
Почему также изменен заголовок меню навигации и как его остановить:
Применяется WordPress the_title
дважды отфильтруйте заголовок пунктов меню навигации (если пункты меню соответствуют существующим записям или страницам).
Сначала в качестве соответствующего поста или заголовка страницы. Это происходит в функции
wp_setup_nav_menu_item()
файлаwp-includes/nav-menu.php
.Затем в качестве самого заголовка пункта меню. Это происходит в классе
Walker_Nav_Menu
.
По вашему требованию нам нужно остановить фильтр the_title
оба раза.
К счастью, в WordPress есть два фильтра: pre_wp_nav_menu
срабатывает перед фильтрацией заголовков меню и wp_nav_menu_items
срабатывает после фильтрации заголовков меню. Таким образом, мы можем использовать эти два фильтра, чтобы сначала удалить фильтр the_title
для заголовков пунктов меню навигации, а затем снова добавить фильтр the_title
для других заголовков.
КОД
Вы можете использовать следующий КОД в файле темы functions.php
или в качестве отдельного плагина:
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 );
Редактор навигации WordPress имеет возможность изменять название меню независимо от названия поста/страницы.
Если вам нужно более автоматизированное решение, приведенный ниже код заменит заголовок сообщения/страницы везде с помощью фильтра the_title
, но восстановит заголовок пункта меню по умолчанию с помощью фильтра nav_menu_item_title
.
/**
* 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 );
Если у вас есть объект post (get_the_id(); или $post->ID; по сути, это одно и то же) См. https://stackoverflow.com/questions/22351038/get-the-current-page-id-inside-wordpress-plugin-page, тогда вы также должны быть в состоянии использовать либо https://developer.wordpress.org/reference/functions/get_post_type / для проверки типа или
if (in_array($post->post_type, array('post', 'page')) {
... swop the title
}