I need to trigger the 404.blade.php template when a “post” page is opened.
Basing on this article, I’m trying this inside filters.php:
add_action( 'template_redirect', function() {
if ( ! is_singular( 'post' ) )
return;
// 1. Ensure `is_*` functions work
global $wp_query;
$wp_query->set_404();
// 2. Fix HTML title
add_action( 'wp_title', function () {
return '404: Not Found';
}, 9999 );
// 3. Throw 404
status_header( 404 );
nocache_headers();
// 4. Show 404 template
require get_404_template();
//get_template_part( 404 );
//include( get_query_template( '404' ) );
// 5. Stop execution
exit;
} );
but it returns a blank page with the blade code inside 404.blade.php:
@extends('layouts.app') @section('content')
@if (!have_posts())
{{-- {!! get_search_form(false) !!} --}} @endif
@endsection
How can solve?
Thanks
Blade templates need to be compiled to PHP and then output, rather than included directly like a standard WordPress template file. So, if everything is working except you’re seeing the raw Blade code rather than the rendered template, then you probably just need to use the template() function to compile your template and then echo the result.
Try something like echo template(get_404_template()); instead of require get_404_template();.
Hi @mmirus
awesome, we’re almost there. Now it renders the 404 template but from there I don’t have the variables passed by the App.php controller.
I placed @debug in the 404 template and indeed it prints nothing.
You know why?
Thanks!
When you call a Blade template using template(get_404_template()) you need to pass variables too it directly; it won’t automatically inherit them from context. i.e. template(get_404_template(), ['variable_name' => 'some data']).
Is there a reason you can’t do the same thing with pre_get_posts and just turn all post requests into 404s before you get to template_redirect? i.e.:
add_action('pre_get_posts', function(query) {
if ( $query->is_single ) {
$query->set_404();
}
});
Yes, I could use pre_get_posts but your code catch all single (including custom post type single), while I need to catch only “post” single (not custom post types). How can do it?
Also, should I add this steps?
// 2. Fix HTML title
add_action( 'wp_title', function () {
return '404: Not Found';
}, 9999 );
// 3. Throw 404
status_header( 404 );
nocache_headers();
// 5. Stop execution
exit;
My code is just an example to get you started, not a literal replacement. There are a lot of conditionals on the $query object that you can check to make sure it only runs on the correct post type: Class Reference/WP Query « WordPress Codex
Does it work if you don’t?
Hi @alwaysblank I’m trying to catch the “post” single but I can’t make it works. 
None of the following worked:
if ( $query->is_singular('post') ) ...
if ( $query->is_single('post') ) ...
if ( $query->query_vars['post_type'] == 'post' ) ...
if ( $query->get('post_type') === 'post' ) { ...
Some help?
My first step is to check if my conditional is working by adding some code that I know with have an effect I’ll see, like die("I work!"), to see if it’s my conditional that’s not working, or the actual effect I’m shooting for (in your case forcing a 404) not firing.
i.e.:
add_action('pre_get_posts', function(query) {
if ( $query->is_single) {
die('I work!');
}
});
Also make sure that the code you’re hooking into pre_get_posts with is firing at a time when it’s possible for it to hook into that action.
Hi @alwaysblank, tried your code and it prints I work! on any single post types, while I need it worked just for default single post (not custom post types)
I think the conditional $query->is_single catches any single and I can’t find the one I need…
Maybe try var_dump($query) before die() and then load one page with the standard post type and one with a custom post type? That way you should be able to find a property of $query that you can use in combination with the code that you got from @alwaysblank to target only the standard post type.
Hi @folbert, tried your idea and these are what they outputs:
"post" type => http://localhost:3000/hello/
object(WP_Query)#340 (47) { ["query"]=> array(2) { ["page"]=> string(0) "" ["name"]=> string(4) "hello" } ["query_vars"]=> array(53) { ["page"]=> string(0) "" ["name"]=> string(4) "hello" ["error"]=> string(0) "" ["m"]=> string(0) "" ["p"]=> int(0) ["post_parent"]=> string(0) "" ["subpost"]=> string(0) "" ["subpost_id"]=> string(0) "" ["attachment"]=> string(0) "" ["attachment_id"]=> int(0) ["static"]=> string(0) "" ["pagename"]=> string(0) "" ["page_id"]=> int(0) ["second"]=> string(0) "" ["minute"]=> string(0) "" ["hour"]=> string(0) "" ["day"]=> int(0) ["monthnum"]=> int(0) ["year"]=> int(0) ["w"]=> int(0) ["category_name"]=> string(0) "" ["tag"]=> string(0) "" ["cat"]=> string(0) "" ["tag_id"]=> string(0) "" ["author"]=> string(0) "" ["author_name"]=> string(0) "" ["feed"]=> string(0) "" ["tb"]=> string(0) "" ["paged"]=> int(0) ["meta_key"]=> string(0) "" ["meta_value"]=> string(0) "" ["preview"]=> string(0) "" ["s"]=> string(0) "" ["sentence"]=> string(0) "" ["title"]=> string(0) "" ["fields"]=> string(0) "" ["menu_order"]=> string(0) "" ["embed"]=> string(0) "" ["category__in"]=> array(0) { } ["category__not_in"]=> array(0) { } ["category__and"]=> array(0) { } ["post__in"]=> array(0) { } ["post__not_in"]=> array(0) { } ["post_name__in"]=> array(0) { } ["tag__in"]=> array(0) { } ["tag__not_in"]=> array(0) { } ["tag__and"]=> array(0) { } ["tag_slug__in"]=> array(0) { } ["tag_slug__and"]=> array(0) { } ["post_parent__in"]=> array(0) { } ["post_parent__not_in"]=> array(0) { } ["author__in"]=> array(0) { } ["author__not_in"]=> array(0) { } } ["tax_query"]=> NULL ["meta_query"]=> bool(false) ["date_query"]=> bool(false) ["post_count"]=> int(0) ["current_post"]=> int(-1) ["in_the_loop"]=> bool(false) ["comment_count"]=> int(0) ["current_comment"]=> int(-1) ["found_posts"]=> int(0) ["max_num_pages"]=> int(0) ["max_num_comment_pages"]=> int(0) ["is_single"]=> bool(true) ["is_preview"]=> bool(false) ["is_page"]=> bool(false) ["is_archive"]=> bool(false) ["is_date"]=> bool(false) ["is_year"]=> bool(false) ["is_month"]=> bool(false) ["is_day"]=> bool(false) ["is_time"]=> bool(false) ["is_author"]=> bool(false) ["is_category"]=> bool(false) ["is_tag"]=> bool(false) ["is_tax"]=> bool(false) ["is_search"]=> bool(false) ["is_feed"]=> bool(false) ["is_comment_feed"]=> bool(false) ["is_trackback"]=> bool(false) ["is_home"]=> bool(false) ["is_privacy_policy"]=> bool(false) ["is_404"]=> bool(false) ["is_embed"]=> bool(false) ["is_paged"]=> bool(false) ["is_admin"]=> bool(false) ["is_attachment"]=> bool(false) ["is_singular"]=> bool(true) ["is_robots"]=> bool(false) ["is_posts_page"]=> bool(false) ["is_post_type_archive"]=> bool(false) ["query_vars_hash":"WP_Query":private]=> string(32) "267f226a4936902f26db6f23ef85759d" ["query_vars_changed":"WP_Query":private]=> bool(false) ["thumbnails_cached"]=> bool(false) ["stopwords":"WP_Query":private]=> NULL ["compat_fields":"WP_Query":private]=> array(2) { [0]=> string(15) "query_vars_hash" [1]=> string(18) "query_vars_changed" } ["compat_methods":"WP_Query":private]=> array(2) { [0]=> string(16) "init_query_flags" [1]=> string(15) "parse_tax_query" } } I work!
"experience" post type => http://localhost:3000/experiences/experience-1/
object(WP_Query)#340 (47) { ["query"]=> array(4) { ["page"]=> string(0) "" ["experience"]=> string(27) "experience-1" ["post_type"]=> string(10) "experience" ["name"]=> string(27) "experience-1" } ["query_vars"]=> array(55) { ["page"]=> string(0) "" ["experience"]=> string(27) "experience-1" ["post_type"]=> string(10) "experience" ["name"]=> string(27) "experience-1" ["error"]=> string(0) "" ["m"]=> string(0) "" ["p"]=> int(0) ["post_parent"]=> string(0) "" ["subpost"]=> string(0) "" ["subpost_id"]=> string(0) "" ["attachment"]=> string(0) "" ["attachment_id"]=> int(0) ["static"]=> string(0) "" ["pagename"]=> string(0) "" ["page_id"]=> int(0) ["second"]=> string(0) "" ["minute"]=> string(0) "" ["hour"]=> string(0) "" ["day"]=> int(0) ["monthnum"]=> int(0) ["year"]=> int(0) ["w"]=> int(0) ["category_name"]=> string(0) "" ["tag"]=> string(0) "" ["cat"]=> string(0) "" ["tag_id"]=> string(0) "" ["author"]=> string(0) "" ["author_name"]=> string(0) "" ["feed"]=> string(0) "" ["tb"]=> string(0) "" ["paged"]=> int(0) ["meta_key"]=> string(0) "" ["meta_value"]=> string(0) "" ["preview"]=> string(0) "" ["s"]=> string(0) "" ["sentence"]=> string(0) "" ["title"]=> string(0) "" ["fields"]=> string(0) "" ["menu_order"]=> string(0) "" ["embed"]=> string(0) "" ["category__in"]=> array(0) { } ["category__not_in"]=> array(0) { } ["category__and"]=> array(0) { } ["post__in"]=> array(0) { } ["post__not_in"]=> array(0) { } ["post_name__in"]=> array(0) { } ["tag__in"]=> array(0) { } ["tag__not_in"]=> array(0) { } ["tag__and"]=> array(0) { } ["tag_slug__in"]=> array(0) { } ["tag_slug__and"]=> array(0) { } ["post_parent__in"]=> array(0) { } ["post_parent__not_in"]=> array(0) { } ["author__in"]=> array(0) { } ["author__not_in"]=> array(0) { } } ["tax_query"]=> NULL ["meta_query"]=> bool(false) ["date_query"]=> bool(false) ["post_count"]=> int(0) ["current_post"]=> int(-1) ["in_the_loop"]=> bool(false) ["comment_count"]=> int(0) ["current_comment"]=> int(-1) ["found_posts"]=> int(0) ["max_num_pages"]=> int(0) ["max_num_comment_pages"]=> int(0) ["is_single"]=> bool(true) ["is_preview"]=> bool(false) ["is_page"]=> bool(false) ["is_archive"]=> bool(false) ["is_date"]=> bool(false) ["is_year"]=> bool(false) ["is_month"]=> bool(false) ["is_day"]=> bool(false) ["is_time"]=> bool(false) ["is_author"]=> bool(false) ["is_category"]=> bool(false) ["is_tag"]=> bool(false) ["is_tax"]=> bool(false) ["is_search"]=> bool(false) ["is_feed"]=> bool(false) ["is_comment_feed"]=> bool(false) ["is_trackback"]=> bool(false) ["is_home"]=> bool(false) ["is_privacy_policy"]=> bool(false) ["is_404"]=> bool(false) ["is_embed"]=> bool(false) ["is_paged"]=> bool(false) ["is_admin"]=> bool(false) ["is_attachment"]=> bool(false) ["is_singular"]=> bool(true) ["is_robots"]=> bool(false) ["is_posts_page"]=> bool(false) ["is_post_type_archive"]=> bool(false) ["query_vars_hash":"WP_Query":private]=> string(32) "438563e1c3e1141da50810663a05029d" ["query_vars_changed":"WP_Query":private]=> bool(false) ["thumbnails_cached"]=> bool(false) ["stopwords":"WP_Query":private]=> NULL ["compat_fields":"WP_Query":private]=> array(2) { [0]=> string(15) "query_vars_hash" [1]=> string(18) "query_vars_changed" } ["compat_methods":"WP_Query":private]=> array(2) { [0]=> string(16) "init_query_flags" [1]=> string(15) "parse_tax_query" } } I work!
I can’t see a property to targets the standard post type. Am I wrong?
p.s. notice that I also have to trigger the 404 for standard “post” archives
My bad. $query doesn’t seem to hold any post data that can be easily used to determine the post type when called using the pre_get_posts filter.
But what if you use the filter template_include instead of the action template_redirect that you used in your original post? As taken from the documentation for template redirect: “Loading a different template is not a good use of this action hook.”
Something like:
add_action('template_include', function($template) {
if (is_singular('post')) {
global $wp_query;
$wp_query->set_404();
// In case you need to make sure that `have_posts()` return false.
// Maybe there's a reset function on WP_Query but I couldn't find one.
$wp_query->post_count = 0;
$wp_query->posts = [];
$wp_query->post = false;
status_header(404);
$template = get_404_template();
}
return $template;
});
Wow @folbert it seems work well! It renders the Blade template and I have also the variables passed by App.php controller. Awesome.
Just some details to understand.
-
Basing on this article, he adds add_action(wp_title)... and nocache_headers(); and exit at the end. You didn’t add them in your code. Are they unnecessary?
-
How can I return 404 also for standard post archive? In general I need to return 404 for all URL related to standard post
Thanks a lot
Thanks @folbert
Placing exit before the return I get browser 404 page (no WP template loaded), while placing it after the return it works identical (it loads the WP 404 template).
Do you think is better to add it or not?
If you read the manual for exit (and maybe also return), I am sure that you will find the answer yourself 