Fallback for "get specific page by UID"

I guess I’m not the only one that uses some sort of “get specific page by UID” on every single project with Kirby.
While I’m sure there are some other options, these are the three methods I use:

  • page(‘UID’)
  • $site->index()->find(‘UID’)
  • $site->index()->filterBy(‘uid’, ‘UID’)

Unless you use a custom unique ID field for your pages, the UID is the field that should be unique. Using the panel, you can use an UID multiple times though. Just not under the same parent.
Also, it’s obviously possible to change the UID in the panel. And there’s no option to set the UID to be read-only I think.

But what happens when the “get specific page by UID” fails?
When it either doesn’t find a page with the UID or finds multiple pages with the same UID?

For the latter, I noticed it will always just take the first occurrence. I think that’s fine in most cases.

But if there’s no page with the UID, it breaks the frontend. There will be a “Fatal Error” stating “Uncaught Error: Call to a member function url() on boolean…” and no more code will be displayed after that.
One time, a client of mine changed the “News” page name and UID. The whole page was broken after that, and he didn’t even understand what happened. Well, the latest news are displayed on every page…
If “debug” is set to “false” or the error is displayed in an attribute, it’s just a blank page with no visible error message at all.

There were some discussions on the Kirby Forum, and also the wonderful Auto ID plugin by @helllicht I use on some projects. But I still think the UID is the go-to ID for most Kirby pages.

Would it make sense to optimize the error handling for “UID not found”? Or adding an option to lock a page UID in the blueprint?

1 Like

I agree that using the uid to find pages is risky. I read somewhere that user permissions are supposed to bring the option to lock changing of the url. Unfortunately, currently it is not possible to lock this function (nor the visibility toggle). You could try to hide the link via a custom stylesheet, though.

Some alternatives: In your templates, you could try to find pages by another field that you set to readonly. In cases where a page has a template that is not used for other pages, you could find your page by template. You could also use help text for pages whose UID should not be changed.

Thanks Sonja!

That’s good to know. I think it definitely makes sense to lock the UID for some users.
As I wrote in my initial post, I already use the AutoID plugin which generates an unique ID set to readonly.

But I still think it’s not ideal to have an error break the whole page. If the “news” code snippet would have been skipped and the “news” sidebar would have been displayed empty, my client probably knew what he did wrong.
Wouldn’t it be better to have a non-fatal error for something like that?

Generally it makes sense to always validate the result value to avoid doing stuff with the page if it doesn’t exist:

<?php if($p = page('uid')): ?>
  // output data
<?php else: ?>
  This data is currently not available.
<?php endif ?>

This approach also makes it possible to use your own error messages and error layouts.

1 Like

Thanks Lukas! I didn’t know it was possible to check the existence of the page without an error. But it makes sense. It’s even a lot easier to change the UID in the template with a variable.