- Published on
User profile urls in CraftCMS
- Authors
- Name
- Leevi Graham
- @leevigraham
Unlike Entries
and Categories
, Users
don't have a URI Format
setting. This means {{ user.getUrl() }}
method returns a blank string. Here's how to fix that in CraftCMS v4.3.0.
INFO
This article assumes you're using CraftCMS v4.3.0 or later.
CraftCMS entries (and categories) have a setting called URI Format
. This allows you to easily call {{ entry.getUrl() }}
in your templates.
Users
do not have this setting which requires developers to add custom url code in their templates. Usually something like:
{{ url("users/"~user.username) }}
This is fine but it's not ideal. It's also not very flexible. What if you want to change the url format? You'll need to update all your templates.
Adding a .url()
method to Users
First thing you might try is adding a custom behaviour to Users with a getUrl()
method. Unfortunately this won't work because User
is an Element
and Element
's already have a getUrl()
method which can't be overwritten in a Behaviour
.
INFO
If you're using CraftCMS < v4.3.0 you could still use a behaviour and add a getProfileUrl()
method.
Looking at the Element::getUrl()
(committed on Oct 21, 2022) method we can see there is a User::EVENT_DEFINE_URL
event that is fired before the url is returned. We can use this to add our own logic.
Create a module
Step 1: Follow the instructions on the CraftCMS website to create a custom module.
Step 2: Add the following code to your module's init()
method:
<?php
namespace foo;
use Craft;
class Module extends \yii\base\Module
{
public function init()
{
// ...
// Defer most setup tasks until Craft is fully initialized:
Craft::$app->onInit(function() {
// Add the event listener
\craft\base\Event::on(
User::class,
Element::EVENT_DEFINE_URL,
function (DefineUrlEvent $event) {
$event->handled = true;
// Add your custom url logic here
$event->url = UrlHelper::siteUrl('users/' . $event->sender->id);
// Other examples:
// $event->url = UrlHelper::siteUrl('users/' . $event->sender->username);
// $event->url = UrlHelper::siteUrl('users/' . $event->sender->uuid);
}
);
});
}
}
Step 3: Test it out by adding the following to your template:
{{ user.getUrl() }}