如何为管理员端插件的使用添加_title前缀

时间:2016-02-29 作者:Andre Bulatov

当我这样做时:

function append_album_review_to_title( $title ) {
    global $post;
    if ( get_post_type( $post->ID ) == \'album_review\' && in_the_loop() ){
        return \'Album Review: \' . $title;
    } else {
        return $title;
    }
}
add_filter(\'the_title\', \'append_album_review_to_title\');
标题已正确添加到,但仅在查看实际页面时。

当我不通过删除&& in_the_loop(), 它正确地为我用来将我发布的帖子自动共享到Twitter的插件输出的标题加上前缀。然而,问题是,如果我不测试循环,字符串也会在每个nav菜单项名称的前面

我可以使用哪些条件语句来测试导航菜单项并在筛选器中跳过它们?

更新1谢谢Ittikorn。我试过了,但没用。我可以看到它正在改变<title> 但不幸的是,共享插件的输出仍然是原来的标题。

非常感谢更新2,虽然如果我能做出更详细、更有见地的回答,两人都会得到我真正的支持,但不幸的是,Sumit或Peter提供的解决方案都不起作用。

Sumit的解决方案的工作原理是,它没有通过对导航菜单项应用过滤器来不必要地破坏导航菜单项,但它也没有将过滤器应用于屏幕后自动社交共享插件,这正是我所需要的。

Peter的解决方案也不起作用,与Sumit的解决方案完全相同。我尝试过使用它,但无法将其定位为in\\u the\\u循环和社交共享插件的帖子标题,但无法用于nav菜单项。

彼得和苏米特的答案确实给了我极大的帮助,并最终让我找到了解决方案。

尝试这两种答案时,我注意到,在后端,插件会返回“缺少参数2”和“注意:尝试获取非对象的属性…”之类的警告,因此我想到,与前端(导航菜单和循环)不同,在后端,显然是$id 未传递给the_title 所以我可以用它作为条件。

这段代码完成了我所需要的(即,在循环中修改帖子标题,不修改导航菜单项,以及修改the_title 供后端社交共享插件使用):

function append_album_review_to_title( $title, $id = NULL ) {
    if ($id) {
        if ( get_post_type( $id ) == \'album_review\' ){
            return \'Album Review: \' . $title;
        } else {
            return $title;
        }
    } else {
        return \'Album Review: \' . $title;
    };
}
add_filter(\'the_title\', \'append_album_review_to_title\', 10, 2);
如果您认为我可以以某种方式改进,或者如果无人参与,这可能会导致未来的问题,请告诉我。谢谢你的帮助。

4 个回复
最合适的回答,由SO网友:Andre Bulatov 整理而成

解决方案

function append_album_review_to_title( $title, $id = NULL ) {
    if ($id) {
        if ( get_post_type( $id ) == \'album_review\' ){
            return \'Album Review: \' . $title;
        } else {
            return $title;
        }
    } else {
        return \'Album Review: \' . $title;
    };
}
add_filter(\'the_title\', \'append_album_review_to_title\', 10, 2);
解释尽管两种解决方案都不完全有效,但彼得和苏米特的答案确实给了我极大的帮助,最终让我找到了解决方案。

在尝试Sumit和Peter的答案时,我注意到在后端,插件会返回如下警告missing parameter 2Notice: Trying to get property of non-object..., 因此我想到,与前端(导航菜单和循环)不同,在后端,显然是$id 未传递给the_title 所以我可以用它作为条件。

这段代码完成了我所需要的(即,在循环中修改帖子标题,不修改导航菜单项,以及修改the_title 供后端社交共享插件使用):

SO网友:Sumit

问题是全球性的$post. 正如@Pieter建议的全球$post 对象可以随时使用其他插件或代码进行更改。菜单项受影响,因为全局$post 不包含正确的对象。

而不是$post, the_title 过滤器还为您提供当前正在运行的帖子的ID,所以请以这种方式使用它

function append_album_review_to_title( $title, $id ) {
    if ( get_post_type( $id ) == \'album_review\' ){
        return \'Album Review: \' . $title;
    } else {
        return $title;
    }
}
add_filter(\'the_title\', \'append_album_review_to_title\', 10, 2);

SO网友:Pieter Goosen

重新安排答案以避免混淆

虽然以下解决方案可能有效,但并不理想

add_filter( \'the_title\', function ( $title, $post_id )
{
    if ( \'album_review\' === get_post_type( $post_id ) )
        $title = \'Album Review: \' . $title;

    return $title;
}, 10, 2 );
问题是,任何使用the_title()get_the_title() 将受此筛选器的影响,其中包括所有查询和导航菜单。如果您有来自album_review 在导航菜单中输入后,此过滤器也会作用于这些标题。

正如您正确指出的那样in_the_loop() 条件仅针对主查询的目标,没有与目标自定义查询和导航菜单项类似的内容。

模板标记的最大问题是the_title()the_content() 因为他们不知道使用它们的上下文,这使得他们很难成为目标。

仅从导航菜单中删除标题过滤器可能是一个相当大的问题,因为正如我所说,the_title() 不知道使用它的上下文。我能想到的唯一可能的方法是在wp_nav_menu_args 在导航菜单项标题之前运行的过滤器,然后通过wp_page_menu 或者wp_nav_menu 过滤器,取决于是否设置了回退

您可以尝试以下操作:

add_filter( \'wp_nav_menu_args\', function ( $args )
{
    // Remove the title filter for a while so we do not alter nav menu titles
    remove_filter( \'the_title\', \'wpse_219222_customize_title\', 10, 2 );

    // Re-apply the title filter after we add titles
    $filter = ( \'wp_page_menu\' === $args[\'fallback_cb\'] ) ? \'wp_page_menu\' : \'wp_nav_menu\';
    add_filter( $filter, \'wpse_219222_add_title_filter_back\' );

    return $args;
});

function wpse_219222_add_title_filter_back( $nav_menu )
{
    add_filter( \'the_title\', \'wpse_219222_customize_title\', 10, 2 );

    return $nav_menu;
}

/**
 * Our custom call back function which will be hooked to the_title filter
 */
function wpse_219222_customize_title( $title, $post_id )
{
    if ( \'album_review\' === get_post_type( $post_id ) )
        $title = \'Album Review: \' . $title;

    return $title;
}
其他有用信息-如果需要,要从其他查询中删除筛选器,如果需要将筛选器应用于特定查询,我喜欢将自定义查询变量传递给查询,然后在中进行检查pre_get_posts 然后用它来决定是否必须应用我的过滤器。类似以下内容将在自定义查询中起作用

add_action( \'pre_get_posts\', function ( $q )
{
    if ( 1 === $q->get( \'custom_title\' ) )
    {
        add_filter( \'the_title\', function ( $title, $post_id )
        {
            if ( \'album_review\' === get_post_type( $post_id ) )
                $title = \'Album Review: \' . $title;

            return $title;
        }, 10, 2 );
    }
});
然后你就可以通过\'custom_title\' => 1 将筛选器仅应用于该特定查询

出于兴趣和玩转的目的,您也可以这样做,以主页上的主查询和任何自定义查询为目标\'custom_title\' => 1 已通过

add_action( \'pre_get_posts\', function ( $q )
{
    if (    $q->is_home()
         && $q->is_main_query() 
    ) {
        $q->set( \'custom_title\', 1 );
    }

    if ( 1 === $q->get( \'custom_title\' ) )
    {
        add_filter( \'the_title\', function ( $title, $post_id )
        {
            if ( \'album_review\' === get_post_type( $post_id ) )
                $title = \'Album Review: \' . $title;

            return $title;
        }, 10, 2 );
    }
});
Here 是@birgire提出的另一个很棒的过滤想法,如果您需要在小部件中只针对帖子标题,可以对其进行调整和修改

您可以将此方法与所有其他方法结合使用,并且您认为合适

SO网友:Ittikorn S.

尝试使用wp_title 筛选而不是the_title 在标题元标记上重写

add_filter(\'wp_title\', \'append_album_review_to_title\');