Honestly this should be a lot easier than actually is. The simplest way is to implement a 404.html page on your theme/templates folder but that means a static and hardcoded approach. Furthermore you might be using a language plugin like Polylang and you’d like to show different posts translations depending on the present language.
Most commun but not correct approach
A common solution is to use the filter template_redirect
, this is not a good idea because what we want is to change the WP_Query selected Post and if you do that on the template_redirect filter it might be overwritten later in the script.
The 404_template filter
The best way to show a custom wordpress post when a 404 happens is using the add_filter('404_template')
and then create a new WP_Query instance pointing to the Post you’d like to show.
First create the WordPress Post you’d like to use and then use the 404_template filter
Example of code below:
add_filter('404_template',function($template, $type, $templates){
$request_uri = $_SERVER['REQUEST_URI'];
if (stripos($request_uri, '/wp-content/uploads/') === false) {//this check is done because if a file like na image is not found the 404_template filter is called
global $wp_query;
$not_found_page_id = 1;//this is an example, if you are using Polylang you can use pll_get_post(1);
$wp_query = new WP_Query([
'post_type'=>'page',
'p'=>$not_found_page_id
]);
}
return $template;
},3,10);