1

I am creating a multilingual site, and trying to hook on to parse_query to throw a 404 if a specific translation doesn't exist (I have my own function to do the actual checking).

I can successfully throw a 404 if the language query var is not valid, but post_id's cannot be found (I have tried global $post, get_the_ID(), get_queried_object_id() etc).

$wp_query->get ('page_id) returns the ID of a page only, so not useful when on posts and custom post types.

Below is my current code:

function wf_lang_parse_query( $wp_query ) {
    
    if ( !is_admin() && ( $wp_query->get( 'lang' ) && !in_array( $wp_query->get( 'lang' ), wf_valid_lang() ) ) ):

        $wp_query->set_404();
        status_header( 404 );

    elseif ( !is_admin() &&  !wf_check_if_has_translations(THE ID GOES HERE, $wp_query->get( 'lang' )) ):

        $wp_query->set_404();
        status_header( 404 );

    endif;
    
}
add_action( 'parse_query', 'wf_lang_parse_query' );

Is it because that I am hooking on too early before post_id is available? Is there a hook that is available a bit later where I can get the Post ID and throw a 404 without causing issues?

4
  • This related question might help: wordpress.stackexchange.com/questions/191877/…
    – WebElaine
    Commented Jul 29, 2022 at 13:03
  • Also, have you tried the pre_get_posts hook? That might have more query details available.
    – WebElaine
    Commented Jul 29, 2022 at 13:04
  • global $post, get_the_ID(), get_queried_object_id() etc won't be available until after the query has ran, parse_query is too early and WP has only just figured out what the query vars should be, it hasn't fetched any posts or gone to the database yet. The same will be true of pre_get_posts. Likewise you need to check if the query is singular or not, you don't want to do this on a post archive/RSS feed/search/REST API listing/etc, and you need to check if it's the main query or not, otherwise your 404 will give warnings halfway down the page for widgets etc
    – Tom J Nowell
    Commented Jul 29, 2022 at 13:12
  • also in some situations it won't know if there's a post that has been found yet, because maybe the query variable is name=foo and it won't know until it's gone to the database yet. Perhaps a later hook that's not related to query parsing would be more appropriate for this specific check. You should keep your check on the lang values validity here though, maybe even earlier
    – Tom J Nowell
    Commented Jul 29, 2022 at 13:16

1 Answer 1

1

Thank you for your responses. After a bit of testing, I hooked onto WP (https://developer.wordpress.org/reference/hooks/wp/) which occurs near the end of the WordPress loading sequence, and it is now working:

function wf_lang_query_check() {
    
    global $wp_query, $post;
    
    $lang =  wf_get_lang();
        
    if ( ( !is_admin() && $wp_query->is_main_query() ) && ( $lang && ( !in_array(  $lang, wf_valid_lang() ) || !wf_check_if_has_translations($post->ID,  $lang ) ) ) ):
    
       $wp_query->set_404();
       status_header( 404 );
        
    endif;
    
}
add_action( 'wp', 'wf_lang_query_check' );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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