Omitting a folder with more than one sub-level

Hi there,
i have a route i am using to omit a top level folder. I got this from the docs on how to omit the blog/ folder:

'routes' => [
    [
        'pattern' => '(:any)',
        'action'  => function($uid) {
            $page = page($uid);
            if(!$page) $page = page('blog/' . $uid);
            if(!$page) $page = site()->errorPage();
            return site()->visit($page);
        }
    ],
    [
        'pattern' => 'blog/(:any)',
        'action'  => function($uid) {
            go($uid);
        }
    ]
]];

This works fine if there is just one level of subpages in the blog folder, but it doesn’t with more sublevels. Is there a way to employ the "Mighty mighty URI-Objects (I can’t find this article anymore on the kirby site) to do this?
I am searching for an expression that would say: ‘blog/’. page URI minus the first folder…

You can use the (:all) instead of the (:any) placeholder for a catch all route.

Thanks for the quick reaction. Changing from any to all didn’t really change anything on my end. I thought it has more to do with this line:
if(!$page) $page = page(‘blog/’ . $uid);
because it only constructs a url with “blog” and the next subfolder uid, while all the folders in between the current UID and “blog” get ignored…

Well, yes, of course you have to handle other pages as well, the easiest is probably this (not tested):

'action'  => function($uri) {
            $page = page($uri);
            if(!$page) $page = page('blog/' . $uri);
            if ($page) {
               return site()->visit($page);
            }
            $this->next();
        }

thanks, @texnixe. This doesn’t work either, and now i am starting to loose track on what it means.
but what i think shouldn’t work is this: ‘blog/’.$uri should create a url like this:
“blog/blog/currentpage” because the $uri object already contains the blog part, right? i was just wondering if there is a way to construct a path with “blog”.$uri-without-the-first-level.

But i am not sure, since i can’t really read and understand even the original blog function… I can only assume that the line
if(!$page) $page = page(‘blog/’ . $uid);
basically lays out the case of a subpage of “blog”.

now i got it to work, just by trying:

'routes' => [
    [
        'pattern' => '(:all)',
        'action'  => function($uid) {
        $page = page($uri); // $uri is not defined!!
        if(!$page) $page = page('blog/' . $uid);
        if ($page) {
           return site()->visit($page);
        }
        $this->next();
    }
    ],
    [
        'pattern' => 'blog/(:all)',
        'action'  => function($uid) {
            go($uri); // $uri is not defined!
        }
    ]
]];

seems to work on my end. i change the uri back to uid and it worked!!!

That doesn’t make sense, you mix both $uid and $uri now (see my comments above), you have to stick with the variable name you pass to the anonymous function, no matter what you call it.

The problem is the order of the routes when using the catch all, this should work:

    'routes' => [
        [
            'pattern' => 'notes/(:all)',
            'action'  => function($uid) {
                return go($uid);
            }
        ],
        [
            'pattern' => '(:all)',
            'action'  => function($uid) {
                $page = page($uid);
                if(!$page) $page = page('notes/' . $uid);
                if(!$page) $page = site()->errorPage();
                return $page;
            }
        ],
    ]

Thanks a lot, @texnixe
This seems to work as well, and i was already wondering about the error page bit…

It it always a pleasure to seek help in this forum. Thanks again!!!

1 Like