I have a taxonomy called "Sports", that includes terms: Football, Rugby, Tennis... What I want to achieve is when (for instance) a post that has the term football is trashed and a visitor try access it, it will be redirected to (for SEO purpose): mywebsite.com/sports/football/ .

I spent many days trying to figure how to do this but in vain. Here is an example of codes I tried:

    function redirect_trashed_posts(){
    if( is_404() ){

        global $wp_query, $wpdb, $post;

        $post_id = $post->ID;

        if( is_object_in_term( $post_id, 'sports' ) ) {

            $terms = get_the_terms( $post_id, 'sports' );
            $term = array_shift( $terms );
            $slug = $term->slug;

            $redirect_to = get_option('siteurl') . '/sports/' . $slug . '/';
            wp_redirect( $redirect_to, 301 );
add_action('template_redirect', 'redirect_trashed_posts');

The main issue is that I can't get the ID of the trashed post and as a consequence the if statement to check if the post belong to "sports" is not working and the "get_the_terms()" returns nothing. I also tried to get data by slug but It did not succeed.

Thanks for your help.


function redirect_trashed_posts(){
    if( is_404() ){ // if page does not exist anymore

        global $wpdb; // so we can talk to db

        // getting current slug__trashed
        // WP append __trashed to trshed posts
        $trashed_post_slug = trim($_SERVER['REQUEST_URI'], '/') . '__trashed'; 

        $post_data = $wpdb->get_row( // requesting ID & post_status from DB
            SELECT ID, post_status
            FROM $wpdb->posts
            WHERE post_name = '$trashed_post_slug'

        $post_id = $post_data->ID; // Getting the ID
        $post_status = $post_data->post_status; // Grabbing the post_status

        if ( $post_status == 'trash'){ // if we are currently on a trashed post
            $terms = get_the_terms( $post_id, 'sports'); // Getting Term, it's an array of objects
            $term = array_shift( $terms ); // Getting first object. I have just one 
            $term_slug = $term->slug; // Getting term slug
            $redirect_to = get_option('siteurl') . '/sports/' . $term_slug . '/'; // full url
            wp_redirect( $redirect_to, 301 ); // 301 redirection

add_action('template_redirect', 'redirect_trashed_posts');

Thanks :D


Try something like

$post_id = url_to_postid($_SERVER['REQUEST_URI']);

Might need some tweaking: might need 'HTTP_REFERER' instead of 'REQUEST_URI'; might need to append the protocol and the domain to the string passed to url_to_postid().

  • Sorry, it did not work. I tried also: (1) global $post; $post_id = $post->ID(); (2) global $wp_query; $post_id = $wp_query->get_queried_object_id(); (3) global $wp_query; $post_id = $wp_query->post->ID; (4) $post_id = get_the_ID(); (5) $post_id = get_query_var(‘page_id’) – Charaf Web Mar 11 '19 at 17:42
  • I added this code to include trashed posts in url_to_postid. But, even with that it did not work – Charaf Web Mar 11 '19 at 18:00

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.