Why does the_title() filter is also applied in menu title?
Asked Answered
V

7

13

I have created below function to hide page title. But when I execute this code, it also hides the menu name.

function wsits_post_page_title( $title ) {
              if( is_admin())

        return $title;

    $selected_type  =   get_option('wsits_page_show_hide');

    if(!is_array($selected_type)) return $title;

    if ( ( in_array(get_post_type(), $selected_type ) ) &&  get_option('wsits_page_show_hide') ) 
    {
        $title = '';
    }
    return $title;
}
add_filter( 'the_title', array($this, 'wsits_post_page_title') );
Villiers answered 19/11, 2012 at 15:8 Comment(2)
Because menu items also have titles and they need to be filtered :). If this is your theme, you can remove the filter before displaying the menu and then adding it again. Alternatively you can do the opposite and add the filter only when you need it.Font
How would someone go about removing a filter and adding it back after displaying the menu title?Laforge
R
16

Nikola is correct:

Because menu items also have titles and they need to be filtered :).

To make this only call in the posts, and not in menus, you can add a check for in_the_loop() - if it is true, you're in a post.

So change the first line in the function to:

if( is_admin() || !in_the_loop() )

and all should be well.

Retiring answered 19/11, 2012 at 15:43 Comment(1)
@Paul This is not working for the widget containing custom menu.Selfcommand
C
7

It's a bit of a hack but you can solve this by adding your action to loop_start.

function make_custom_title( $title, $id ) {
    // Your Code Here
}

function set_custom_title() {
   add_filter( 'the_title', 'make_custom_title', 10, 2 );
}

add_action( 'loop_start', 'set_custom_title' );

By embedding the_title filter inside of a loop_start action, we avoid overwriting the menu title attributes.

Crosswise answered 16/10, 2014 at 8:52 Comment(0)
H
4

You can do something like that :

In your function.php :

add_filter( 'the_title', 'ze_title');
function ze_title($a) {
    global $dontTouch;
    if(!$dontTouch && !is_admin())
        $a = someChange($a);
    return $a;
}

In your template :

$dontTouch = 1;
wp_nav_menu( array('menu' => 'MyMenu') );
$dontTouch = 0;
Hype answered 11/12, 2012 at 22:9 Comment(0)
T
1

Posting this answer because it was the search result I ended up clicking on while searching about targeting the filter hook the_title while ignoring the filter effect for navigation items.

I was working on a section in a theme which I wanted to add buttons to the page title within the heading one tag.

It looked similar to this:

<?php echo '<h1>' . apply_filters( 'the_title', $post->post_title ) . '</h1>'.PHP_EOL; ?>

I was then "hooking in" like this:

add_filter( 'the_title', 'my_callback_function' );

However, the above targets literally everything which calls the_title filter hook, and this includes navigation items.

I changed the filter hook definition like this:

<?php echo '<h1>' . apply_filters( 'the_title', $post->post_title, $post->ID, true ) . '</h1>'.PHP_EOL; ?>

Pretty much every call to the_title filter passes parameter 1 as the $post->post_title and parameter 2 as the $post->ID. Search the WordPress core code for apply_filters( 'the_title'* and you'll see for yourself.

So I decided to add a third parameter for situations where I want to target specific items which call the_title filter. This way, I can still receive the benefit of all callbacks which apply to the_title filter hook by default, while also having the ability to semi-uniquely target items that use the_title filter hook with the third parameter.

It's a simple boolean parameter:

/**
 * @param String $title
 * @param Int $object_id
 * @param bool $theme
 *
 * @return mixed
 */
function filter_the_title( String $title = null, Int $object_id = null, Bool $theme = false ) {

    if( ! $object_id ){
        return $title;
    }

    if( ! $theme ){
        return $title;
    }

    // your code here...

    return $title;

}

add_filter( 'the_title', 'filter_the_title', 10, 3 );

Label the variables however you want. This is what worked for me, and it does exactly what I need it to do. This answer may not be 100% relevant to the question asked, but this is where I arrived while searching to solve this problem. Hope this helps someone in a similar situation.

Toliver answered 23/1, 2017 at 23:1 Comment(0)
O
0

The global $dontTouch; solution didn't work for me for some reason. So I simply removed the filter around the menu thus in header.php:

remove_filter( 'the_title', 'change_title' );
get_template_part( 'template-parts/navigation/navigation', 'top' ); 
add_filter( 'the_title', 'change_title' );

And all is well.

On answered 20/11, 2018 at 15:34 Comment(0)
H
0

I think you're looking for this:

function change_title($title) {
    if( in_the_loop() && !is_archive() ) { // This will skip the menu items and the archive titles
        return $new_title;              
    }    
    return $title;    
}
add_filter('the_title', array($this, 'change_title'), 10, 2); 
Hautesavoie answered 25/1, 2019 at 18:23 Comment(0)
G
0

You can use the post ID to change only the page title:

function replace_page_title( $title, $id = null )   {
// Change the post title only if post ID is eg. 123
if ( $id == 123 ) {
$title = "New Title";
}
return $title;
}
add_filter( 'the_title', 'replace_page_title', 10, 2 );
Gandhiism answered 3/1 at 9:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.