4

I want to have different 404 template for each custom post type.

eg. I have post type name event and the link will be
domain.com/event/my-event-name

but if it link to page that not have post
domain.com/event/xxxxxxx

then it will show 404 page, but I want it different from 404.php template, I try get post type in 404.php but it can't because it not have a post to get from.

1
4

WordPress 4.7 introduces a new filter that allows us to easily modify the template hierarchy:

/**
 * Filters the list of template filenames that are searched for when retrieving 
 * a template to use.
 *
 * The last element in the array should always be the fallback 
 * template for this query type.
 *
 * Possible values for `$type` include: 'index', '404', 'archive', 'author', 'category', 
 * 'tag', 'taxonomy', 'date', 'embed', home', 'frontpage', 'page', 'paged', 'search', 
 * 'single', 'singular', and 'attachment'.
 *
 * @since 4.7.0
 *
 * @param array $templates A list of template candidates, in descending order of priority.
 */
$templates = apply_filters( "{$type}_template_hierarchy", $templates );

For the 404 type, we could check the current path, as suggested by @cjbj.

Here's an example where we modify the 404 template hierarchy by supporting the 404-event.php template, if the current path matches the ^/event/ regex pattern (PHP 5.4+):

add_filter( '404_template_hierarchy', function( $templates ) 
{    
    // Check if current path matches ^/event/ 
    if( ! preg_match( '#^/event/#', add_query_arg( [] ) ) )
        return $templates;

    // Make sure we have an array           
    if( ! is_array( $templates ) )
        return $templates;

    // Add our custom 404 template to the top of the 404 template queue
    array_unshift( $templates, '404-event.php' );

    return $templates;
} );

If our custom 404-event.php doesn't exists, then 404.php is the fallback.

We might also just adjust the 404.php template file to our needs, as suggested by @EliCohen

We could also use the old 404_template filter (since WordPress 1.5), that's fired after the locate_template() is called.

Here's an example (PHP 5.4+):

add_filter( '404_template', function( $template ) 
{
    // Check if current path matches ^/event/ 
    if( ! preg_match( '#^/event/#', add_query_arg( [] ) ) )
        return $template;

    // Try to locate our custom 404-event.php template    
    $new_404_template = locate_template( [ '404-event.php'] );

    // Override if it was found    
    if( $new_404_template )
        $template = $new_404_template;

    return $template;
} );

Hope you can test it further and adjust to your needs!

0
1

According to WP's template hierarchy , you cannot use different template to a 404 page. as @Ranuka suggested, you can customize your 404 to display custom content by editing the template file or inserting your own messages.

Read this first: https://developer.wordpress.org/themes/basics/template-hierarchy/ and then decide (and share please) what's your desired solution?

1

A query returns a 404 when there are no results. So, the problem on your 404.php page is that you have no query knowledge about what caused it. Hence, you can't test for a post type.

What you do have, however, is the url that caused the 404. Depending on how you set your permalinks this may contain information about the post type. In the example you give there is /event/ as a string you could test for in your template. Like this:

$url = $_SERVER['REQUEST_URI']; // this will return: /event/my-wrong-event-name or so
if (false === strpos ($url, '/event/')) // important note: use ===, not ==
   ... normal 404 message
else
   ... event 404 message;
1
  • Thanks @cjbj, I have 404 link because of moving from the old site. It indexed in google and I want to make it show the relate template if link is remove for each post type. – supersuphot Nov 15 '16 at 17:58

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