1

I don't know if it was with Craft 3.5, but did something change slightly when using the EVENT_BEFORE_SAVE event?

I have a simple use case where I am encoding the entry ID and updating the slug when the entry is saved. It does check if a title is empty and if the entry is a draft or revision, if any of those are true, then it does not encode it.

After updating from Craft 3.4.30 to Craft 3.5.5 when saving an entry I have noticed that it throws an error as $entry->id returns null, however on refreshing the page and then resaving it, it passes the entry ID in fine.

A basic example of what I have is:

Event::on(
    Entry::class,
    Entry::EVENT_BEFORE_SAVE,
    function (ModelEvent $event) {

        $entry = $event->sender;

        if (ElementHelper::isDraftOrRevision($entry)) {
            return false;
        }

        // Get entry title
        $title = $entry->title;

       if ($title !== null) {
            // Encode entry ID
            $newSlug = Module::$instance->hashid->encode($entry->id);

            // Update slug to be a hash
            $entry->slug = $newSlug;
        }
    }
);

Before hand this worked fine when creating the entry, but now it is requiring me to have to save the entries twice, any thoughts?

  • 1
    If it's a new entry, then $entry->id wouldn't have been set yet (because it hasn't been saved yet) and it doesn't look like your code is taking that into account. Are you sure that's not what you're seeing? – Brad Bell Aug 27 at 19:00
  • This does sound like what the issue is related to. If I were to check isNew, could I then use this Event, or would I have to use EVENT_AFTER_SAVE in this case? – zizther Aug 28 at 10:26
  • You could keep it in this event as long as you checked its newness. – Brad Bell Aug 28 at 19:09
  • Thanks. What is the best way to do this? I want this to apply for new entries which then get an Entry ID and for existing entries. The first part is why i was thinking EVENT_AFTER_SAVE maybe the better solution as it would definitely have an entry ID. Unless there is a nice way to check it with the current event. – zizther Sep 2 at 18:52
1

I did some looking into how the EVENT_BEFORE_SAVE is being used and whether or not we can get the entry ID, without having to over complicate things, it was better to use EVENT_AFTER_SAVE, this does mean you will have to resave the entry after saving it, in this case that is very little overhead and it is only for a certain section, if heavier stuff was happening you may want to check on the impact.

I also placed in a check to detect if the action was happening or not, to stop any loops.

Here is what I ended up doing for anyone who wants to know for reference.

use craft\elements\Entry;
use craft\events\ModelEvent;

const SECTION_ID = 4;
public static $entrySlugRenaming = false;

Event::on(
    Entry::class,
    Entry::EVENT_AFTER_SAVE,
    function (ModelEvent $event) {
        $this->handleEventAfterSave($event);
    }
);

private function handleEventAfterSave($event)
{
    // Get entry
    $entry = $event->sender;

    // Don't worry about draft or revisions
    if (ElementHelper::isDraftOrRevision($entry)) {
        return;
    }

    // Test if entry renaming is already running
    if (!self::$entrySlugRenaming) {
        self::$entrySlugRenaming = true;

        // Check if there is an entry
        if ($entry !== null) {
            // Test for entry section
            switch ($entry->sectionId) {
                case self::SECTION_ID:
                    // Update slug here
                break;
            }
        }

        // Resave event
        $elements = Craft::$app->getElements();
        $elements->saveElement($entry);

        // Reset $entrySlugRenaming
        self::$entrySlugRenaming = false;
    }
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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