3

I'm trying to find a way to change the href of a nav menu page link from the parent theme's default, which goes to its relative page, to another url. For example, I have a menu link "Our Philosophy" that links to the "Our Philosophy" page, but desire for it to go to timecube.com (rip).

It seems perhaps using a filter (nav_menu_link_attributes?) might be a simple way to achieve this. However, I've been unable to wrap my head around using filters to get this working.

I would think I'd need something like:

function change_nav_url( $atts, $item ) {
    // modify $item href?
}
add_filter ( 'nav_menu_link_attributes', 'change_nav_url');

My initial thought would be I would need to call this function somewhere--with apply_filters() maybe--and would need to get $atts and $item manually from somewhere and pass them into it. But that creates the problem--how do I get them, and from what (a menu object?). And thinking about it, if I do have to retrieve them manually, I don't really see the point of using a filter v. a plain function, so maybe I have to put it into the plugin folder and it'll automatically give me access to $atts or something? (That didn't work). Either way, I'm clearly not understanding something.

I appreciate any help bringing light to my newb ignorance.

  • If one of the answers below were helpful please mark it as the accepted answer. – DᴀʀᴛʜVᴀᴅᴇʀ Mar 27 '18 at 16:14
5

You are on right track, with few minor kinks.

  1. You need to modify $atts and return it. Any arguments after the first one are provided for information and should not be changed.
  2. You need to tell add_filter() that you expect more than one argument.

The example with some debug code would be along the lines of:

add_filter( 'nav_menu_link_attributes', function ( $atts, $item, $args, $depth ) {

    var_dump( $atts, $item ); // a lot of stuff we can use

    var_dump( $atts['href'] ); // string(36) "http://dev.rarst.net/our-philosophy/"

    var_dump( get_the_title( $item->object_id ) ); // string(14) "Our Philosophy", note $item itself is NOT a page

    if ( get_the_title( $item->object_id ) === 'Our Philosophy' ) { // for example

        $atts['href'] = 'https://example.com/';
    }

    return $atts;
}, 10, 4 ); // 4 so we get all arguments
  • Thanks for getting back--that's very helpful with the code of where to access / modify the href (also about var_dump, didn't know about that). I'm curious though, is what I was thinking right about just needing to put this add_filter function in a plugin folder to access all the parameters like $atts, $item, or do I need to use apply_filters at all? – Aristoatle Aug 13 '16 at 22:21
  • You don't need to apply filters anywhere, you just need to add to existing filter, which gets applied inside core's menu code. My example is self–sufficient. – Rarst Aug 13 '16 at 22:45
  • So practically, just writing that function somewhere (functions.php or its own .php) is sufficient to have it getting applied / executed via core? Or do I need to activate it as a plugin in Wordpress or something? I tried just putting it in its own .php, as well as some test filters that just echo stuff, but it doesn't seem to do anything. Sorry if this seems a little obtuse... I feel like I'm missing something staring me in the face. – Aristoatle Aug 13 '16 at 23:32
  • You need to put this somewhere that appropriate in what WP loads. This is would typically be a plugin or theme's functions.php file. – Rarst Aug 14 '16 at 8:34
  • Gotcha. I tried it in functions.php along with test output (using echo) but it doesn't seem to do anything. Will try it as a plugin and see what happens – Aristoatle Aug 14 '16 at 18:21
1

This will allow you to update the URL for specific menu items. In the case of the OP, "Link Title" would be replaced with "Our Philosophy".

This would be placed in your child theme's functions.php

 function update_menu_link($items){

    //look through the menu for items with Label "Link Title"
        foreach($items as $item){

            if($item->title === "Link Title"){ // this is the link label your searching for
                $item->url = "http://newlink.com"; //this is the new link
            }
        }
        return $items;
    }

    add_filter('wp_nav_menu_objects', 'update_menu_link', 10,2);
  • The check for if($item->title should be if ( $item->title === 'Link Title' ) - your use of single equals = would assign the value of "Link Title" to $item->title, not compare it. – phatskat Mar 23 '18 at 20:37
  • @phatskat - thanks, I have it updated. It was working correctly, but you are right – dbmpls Mar 27 '18 at 15:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.