How to ignore parts of the URL

Hi there,

for SEO reasons (don’t ask me) I’d like to change my URLs from

https://yves.io/links/2020/05/281255

to

https://yves.io/links/2020/05/281255/_/raspberry-pi-4-mit-8gb-ram-und-beta-fuer-eine-64-bittige-raspberry-pi-os-version-erschienen

I assume I should use Kirby’s routing capabilities for this. But all my tries result in nothing but errors. In theory this addition to my config.php should somehow work:

return [
    'debug' => true,
    'routes' => [
        [
            'pattern' => '(:any)',
            'action'  => function($id) {
                $id = substr($id, strpos($id, '/_/'));
                $page = page($id);
                if(!$page) $page = page($id);
                if(!$page) $page = site()->errorPage();
                    return site()->visit($page);
            }
        ]
    ]
];

But it doesn’t. The code is based in part of this suggestion by @texnixe though there $uid is used instead of $id (I used $id because only this includes all necessary parts of the URI.

Any help is welcome.

If I understand correct, you want that your real URL /2020/05/281255 is returned when the URL /2020/05/281255/_/some-very-long-title is asked by the client? If all your URLs look like this, I would consider adding a rewrite rule to your .htaccess or server config file (not tested):

RewriteRule "^/(.+)/_/.+" "/$1" [PT]

The passthrough option (PT) should make your clients still show the long URL in the browser - if this is something you want.

That’s a charming solution – no idea why I didn’t thought of this. Let’s implement this.

And a big THX!

Hi @Adspectus,

well, somehow the RewriteRule with the [PT] flag doesn’t seem to work and will result in a page not found error meaning Kirby is showing the error page. If I read the Apache documentation correctly those kind of redirects only seem to work with file paths:

http://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_pt

But since I have a directory path some strange mambojumbo in the redirect tree of Kirby happens and resulting ultimately in the above described error message. If I use the [R] flag instead:

 RewriteRule ^(.+)/_/(.+)$ $1 [R]

the user is redirected to the really existing page and no error page is shown.

If I am not totally wrong the solution with a RewriteRule will only work with a real redirect which Google & Co. surely won’t like.

I fear this problem needs to solved within Kirby.

@texnixe: Would you be so kind and re-open this issue? Thanks in advance.

If you want to use a route, it should follow the pattern. (:any) only catches the first part of the URL, so you actually need:

'pattern' => '(:any)/(:any)/(:any)/_/(:any)',
'action'  => function($year, $month, $id, $title) {
  // return the page here
}

(Too bad the 8GB Pi isn’t available yet)

I do not think, that this really matters but maybe the correct placement together with the other rewrite rules from kirby might have an effect. But - as I wrote - I didn’t test this together with Kirby, but the rewrite rule as such should be ok.

You could also achieve that by an optional pattern (and by restricting the year and month param to digits). That makes URLs with and without a title slug accessible:

'pattern' => '([0-9]{4})/([0-9]{2})/(:any)(/)?(:any)?',
'action'  => function($year, $month, $id, $separator = null, $title = null) {
  return page($id) ?? false;
}

Hi all,

thank you all again for your feedback. With all your suggestions I finally was able to solve my issue. Here is the code that made it into my website:

return [
    'debug' => true,
    'routes' => [
        [
            'pattern' => '(:any)/(:any)/(:any)/(:any)/_/(:any)',
            'action'  => function($type,$year, $month, $id, $title) {
                $uid = $type.'/'.$year.'/'.$month.'/'.$id;
                $page = page($uid);
                if(!$page) $page = page($uid);
                if(!$page) $page = site()->errorPage();
                return site()->visit($page);
            }
        ]
    ]
];

Again, many thanks and wish you all a nice, peaceful and healthy weekend.

1 Like