The entries in my Craft app need a unique ‘non-guessable’ URL, so I figured I could use the UID in the URI of the entry.

So in the section, where I need to provide the URI format I entered "section-name/{uid}".

But this is giving me issues, since when I initially save an entry, the URI is "section-name". I think this is because the UID is not available on creation of the URI.

If I save the element for the second time, my problem is solved and the correct URI is generated.

Is there a way to prevent this issue from happening?

I already thought about creating a route, but that means that I need to generate the URI myself in every template, and this is prone to error and not future proof if we would like to change the URI format.

I also thought about creating a module which saves the entry for a second time when a new entry is saved for that section, but I can't find a way to create the correct event-listener.

Does anyone have a better solution or can help me with the event listener in a module?

up vote 2 down vote accepted

I think this can be a starting solution. It rewrite slug of Entry after the Entry is saved to database. The URI is constructed from it. You can try it in any plugin, only register the EVENT_AFTER_SAVE_ELEMENT in init() function of Plugin.

use craft\events\ElementEvent;
use craft\services\Elements;

Event::on(
    Elements::class,
    Elements::EVENT_AFTER_SAVE_ELEMENT,
    function (ElementEvent $event){
        //identify the right Entry for example test sectionId, typeId, authorId
        if ($event->element instanceof craft\elements\Entry) {  
            $entry = $event->element;
            //only newly created 
            if($event->isNew){                  
                $entry->slug = $entry->uid;
                Craft::$app->elements->saveElement($entry);                 
            }
        }
    }
);
  • Thanks, that is exactly what I was looking for. Since I set the URI to /{slug} in the section settings, I did not need to rewrite the slug. So the line $entry->slug = $entry->uid; can be deleted. It was added automatically after saving the second time. I guess because now it has the UID available, and on creation it hasn't. – Dries Oct 8 at 12:06

I may be missing something here, but is the URL of an entry not always unique? How would Craft else know what entry to show?

If you use the entry's slug in the URI (section-name/{slug}), wouldn't that do the trick? A slug is unique within a section and every section has a unique name, so the URL would be unique too. And {slug} is defenitely known in the URI.

It's an old post and may be outdated, but I read here that Craft doesn't expose the UID of an element so maybe that's part of the issue.

  • Thx for your answer Tom. The entries should have a ‘non-guessable’ url. So a uid is ideal. In the current version the uid is exposed. And my idea is working if i save an entry for the secobd time. Probably because a uid is available in the DB by then. – Dries Oct 5 at 14:09
  • Alright, that makes sense. Maybe add that to your question to make it more clear :) – Tom De Smet Oct 5 at 14:13
  • Done 😉 thank you for the reply – Dries Oct 5 at 14:18

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.