web-dev-qa-db-ja.com

メニュータイトルではなく、投稿タイトルとページタイトルでthe_title()フィルタを適用する

WordPress posts pages のタイトルを変更するには、次のコードを使用します。しかし、それはナビゲーションメニュー項目のタイトルも変更するので、避けたいと思います。

ホームページ 、all アーカイブページ およびall ウィジェット (最近の投稿ウィジェット、ランダムな投稿ウィジェットなど)で投稿およびページのタイトルを変更したい。

Stack OverflowとWP St​​ack Exchangeの両方に同様の質問があり、in_the_loop()関数の使用を提案しています。残念ながら、それは私にはうまくいきません。配置した場合、サイドバーウィジェットにも影響するからです。

つまり、in_the_loop()関数を使用しても、the_titleフィルタはrecent posts widgetrandom post widgetなどには影響しません。

それでは、どのように私はpostpageタイトルだけにthe_titleフィルターを適用することができますが、メニュータイトルに適用できないのでしょうか?

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 );
7
Ranuka

問題の説明

最初に質問を言い換えましょう。あなたはしたい:

  1. メタフィールドからすべてのpostおよびpage型に新しいタイトルを設定します。

  2. あなたはこれがいたるところで起こることを望みます(ホームページ、単一ページ、ウィジェットなど)

  3. ただし、タイトルがナビゲーションメニューにある場合は、このタイトルの変更を行わないでください。

溶液:

私があなたにCODEを渡す前に、(あなたのCODEに基づいて)最初にいくつかの点を説明させてください。

すべての投稿とページのタイトルを変更する方法:

あなたはすでに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フィルタを2回適用します(メニュー項目が既存の投稿またはページに対応する場合)。

  1. まず、対応する投稿またはページのタイトルとして。これはwp-includes/nav-menu.phpファイルのwp_setup_nav_menu_item()関数で起こります。

  2. それからメニュー項目のタイトル自体として。これはWalker_Nav_Menuクラスで起こります。

あなたの要件のために、私達はthe_titleフィルターを両方の時間停止する必要があります。

幸いなことに、WordPressには2つのフィルタがあります:pre_wp_nav_menuはメニュータイトルをフィルタリングする前に起動し、wp_nav_menu_itemsはメニュータイトルをフィルタリングした後に起動します。そのため、これら2つのフィルタを使用して、まずナビゲーションメニュー項目のタイトルの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 );
11
Fayaz

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 );
3
kierzniak