4

I am creating a custom WordPress theme using Timber and Twig and I am having a hard time getting my custom 404 page to render.

Originally, each page on my website had a custom route defined in functions.php and my 404 logic was in index.php. This is probably not the best way to accomplish this, but it is the only way I could get it working -- I couldn't find much about creating 404 pages with a custom theme in the Timber documentation.

index.php:

<?php
$context = Timber::get_context();
$post = new TimberPost();
$context['page'] = $post;
global $wp;
$url = home_url($wp->request);
$context['url'] = preg_replace('#^https?://#', '', rtrim($url, '/'));

Timber::render('views/pages/404.twig', $context);

This worked great until I needed to add a wildcard route so that the client could add new pages on their own without asking us to add a new route. I added this wildcard route for pages to functions.php:

Routes::map('/:page', function($params) {
Routes::load('routes/page.php', $params, null, 200);
});

The wildcard route is working as intended, but now my 404 logic from above is no longer working. When I visit a URL that is not a page that has been created in the WordPress admin, it sends me to a page with a random post's content in it. I'm a little lost at how to get this working properly, it is likely that my initial 404 logic is not the correct way to handle it. Any advice would be great.

I have tried to add a 404.php to the theme folder with this code:

<?php
$context = Timber::get_context();

Timber::render( array(
'views/pages/404.twig'
), $context );

This unfortunately did not work -- at a random URL my website is rendering a random post's content and not the 404.twig file.

Liz
  • 1,008
  • 5
  • 19
  • 49

1 Answers1

5

Since you are routing all URLs to 'page.php', there is no way to render '404.php'. Check whether the URL exists first and route accordingly. Change like this in your 'functions.php' which probably solve your 404 issue.

Routes::map('/:page', function ($params) {
    $is_page_exists = get_page_by_path($params['page']);
    if ($is_page_exists) {
        Routes::load('routes/page.php', $params, null, 200);
    } else {
        Routes::load('404.php', $params, null, 404);
    }
});

Then remove 404 related code from your 'index.php'.

I am not sure why you have added this custom route since it will be automatically handled by WordPress / Timber in default (the page slug itself). If you want a custom slug prefix (like http://www.example.com/page/page slug), then you need to have custom route like Routes::map('page/:page', function ($params) { }).

Outsource WordPress
  • 3,749
  • 2
  • 10
  • 23