How to control which category will be picked for the slug of a post?

WordPress picks the lowest ID as its main permalink. However, ALL categories will contain your post automatically. Meaning both these:

…will return your post (given that post-A is in both category-A and category-B) via a redirect. It can’t list them all to you on the Edit page, sorry. But it will make sure they’re available in all categories.

Of course, get_permalink will return the wrong one for you.

http://codex.wordpress.org/Using_Permalinks#Using_.25category.25_with_multiple_categories_on_a_post

Now as for overriding the behavior, look at:

http://core.trac.wordpress.org/browser/tags/3.3.1/wp-includes/link-template.php#L71, specifically a little lower on line 121. It’s going to use $cats[0]->slug after sorting by ID. Which does not appear to be hookable in any way inside there, so either higher or lower.

This is a ticket that was going to change the way it worked http://core.trac.wordpress.org/ticket/18752 it’s marked for Future Release, though. Subscribe to the ticket to show your interest, maybe it makes it into WordPress 3.5 later this year.

The pre_post_link filter will allow you to override the permalink. post_link, too.

Alternatively, get_the_category, should allow you to hack the IDs for a post (or remove the others to leave only one), but this should only occur when the permalink is requested.

add_filter( 'pre_post_link', function( $permalink, $post ) {

     if ( strpos($permalink, '%category%') === false )
         return; /* not interested */
     add_filter( 'get_the_categories', 'wpse46860_prune_categories' );
     return $permalink;

}, null, 2 );

function wpse46860_prune_categories( $categories ) {

    /* run once */
    remove_filter( 'get_the_categories', 'wpse46860_prune_categories' );

    /* .. prune the categories to leave the one you need .. */
    global $_hijack_post_id;

    return $categories;

}

This is a hack.

An additional difficulty is to get the post_ID to prune the categories against, the get_the_categories filter does not pass the post_ID to us; use a global (dirty) or a class property (clean).

You can try out different permalink plugins like:

Leave a Comment