Примените фильтр заголовка() в заголовке публикации и страницы, но не в заголовке меню


Я использую следующий код для изменения названия записей 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 );
Author: Fayaz, 2018-07-21

3 answers

Описание проблемы:

Позвольте мне сначала перефразировать вопрос. Вы хотите:

  1. Установите новый заголовок для всех post и page типов из мета-поля.

  2. Вы хотите, чтобы это происходило везде (домашняя страница, отдельная страница, виджеты и т.Д.)

  3. Однако вы не хотите, чтобы это изменение заголовка происходило, если заголовок находится в меню навигации.

Решение:

Прежде чем я дам вам КОД, позвольте мне объяснить несколько пункты первые (на основе вашего КОДА):

Как изменить названия всех сообщений и страниц:

Вы уже знаете, как использовать фильтр 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 дважды отфильтруйте заголовок пунктов меню навигации (если пункты меню соответствуют существующим записям или страницам).

  1. Сначала в качестве соответствующего поста или заголовка страницы. Это происходит в функции wp_setup_nav_menu_item() файла wp-includes/nav-menu.php.

  2. Затем в качестве самого заголовка пункта меню. Это происходит в классе 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 );
 18
Author: Fayaz, 2018-07-24 04:21:47

Редактор навигации 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 );
 4
Author: kierzniak, 2018-07-25 07:29:28

Если у вас есть объект 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
}
 -1
Author: anmari, 2018-07-21 04:10:01