1

From a custom module, I'm listening to EVENT_AFTER_SAVE_ELEMENT events, to be sure to get the Entry ID after save:

Event::on(
    Elements::class,
    Elements::EVENT_AFTER_SAVE_ELEMENT,
    function (Event $event) {
        if ($event->element instanceof Entry) {
            $entry = $event->element;
            if (ElementHelper::isDraftOrRevision($entry)) {
                $user = Craft::$app->getUser()->getIdentity();
                $user->setFieldValue('myEntriesField', [$event->element->id]);
                Craft::$app->elements->saveElement($user);
            }
        }
    }
);

Unfortunately, the Entries field value is never updated, while the event is correctly caught.

I also tried to move the field update to a service, but nothing change. I also tried to directly changed the field in the database (using Craft::$app->getDb()->createCommand()), but the field isn't found (I can't also find it from the craft_content table).

Any idea why the user's custom field is not updated?

5
  • Have you verified that the hook is actually being called? For example, by writing something to a log or putting a Craft::dd call inside the hook? The hook looks ok, it might just be something silly like a missing use statement for the Entry class. Can you post the entire class including the namespace and imports?
    – MoritzLost
    Sep 17 at 14:11
  • The event is correctly caught. I can dump and exit the code, I can print the $event->element->id value, but the field isn't updated. And of course yii\base\Event, craft\services\Elements, craft\elements\Entry and craft\helpers\ElementHelper are set on top the the file. I get no error. Sep 17 at 14:19
  • I may be wrong, but you probably want your hook to fire only for live entries, right? In this case, your if-statement is missing a !, so the field is only updated when you save drafts or revisions. I'd also simplify the hook a bit, see my answer below.
    – MoritzLost
    Sep 17 at 14:41
  • No, I would like to catch only once after an Entry is created. In my case, I have an account section on front-end, where my user can create an Entry which is assigned to its myEntriesField field after being created. This field belongs to the user, not the Entry. It's an Entry field that will add the newly created Entry to the user's fields. Sep 17 at 15:02
  • I don't want this to be caught on next events, because for example if someone else resave this Entry later it should be not getting it saved to its myEntriesField field. Sep 17 at 15:05
1

Update 2021-09-24

The actual issue is that entries fields can't hold references to drafts only, only to 'real' entries. Drafts have their own ID, but they aren't real entries. The entries field validates this, so any ID that doesn't belong to a realy entries is silently discarded.

If the draft belongs to an entry that is already live, the solution is to add the ID of the live entry to the entries field. If it doesn't, saving the draft in the entries field is impossible.


Old answer

Edit: See comment. The most likely cause is that the field value is only updated if the entry being saved is a draft or revision – usually, you want the reverse. Maybe you're just missing a ! there?

In any case, you can clean your hook up a bit in order to reduce the surface area for bugs. In particular, you can attach the hook to craft\elements\Entry instead of craft\services\Elements, then you can get rid of the instanceof check.

Here's a simplified version of your hook that only applies to drafts and revisions:

use Craft;
use craft\elements\Entry;
use craft\events\ModelEvent;
use craft\helpers\ElementHelper;
use yii\base\Event;

Event::on(
    Entry::class,
    Entry::EVENT_AFTER_SAVE,
    function (ModelEvent $event) {
        $entry = $event->sender;

        if (!ElementHelper::isDraftOrRevision($entry)) return;

        $user = Craft::$app->getUser()->getIdentity();
        $user->setFieldValue('myEntriesField', [$entry->id]);
        $success = Craft::$app->elements->saveElement($user);
        if (!$success) {
            $errors = $user->getErrors();
            // display or log errors
        }
    }
);
10
  • I would like to update field only if ElementHelper::isDraftOrRevision($entry) is true. If I check this, I get an Getting unknown property: craft\events\ModelEvent::element error because of $event->element->id. I can convert it to $entry->id instead, but the field remains not updated. Sep 17 at 15:14
  • @RomainPoirier My bad, I had a bit of the old code in there. I've updated the code example now and switched the logic to only apply to drafts and revisions. Is it still not working with that version? In any case, if you only want the hook to apply to new entries, you'll probably need to add more conditions to handle drafts/revisions. See this question for details.
    – MoritzLost
    Sep 20 at 7:54
  • @RomainPoirier If the field is still not updating correctly, check the return value of the saveElement method – it returns true on success or false on failure. If saving failed, it might be due to a validation error, try dumping or logging $entry->getErrors() after a failed attempt at saving to find any validation errors that prevent the $user element from saving.
    – MoritzLost
    Sep 20 at 7:59
  • The event is still correctly caught. I tried with your version, disabled the previous one, but still get no errors. I can even print the $entry->id value, but the field remains not updated after save... FYI I'm using a multi-sites version, where the Entry belongs to the primary one, and the form is used from the primary site. Sep 20 at 8:23
  • 1
    @RomainPoirier I had another look – so you're trying to assign a a DRAFT to an entries field? I think that might be the problem. Entries fields can only be related to 'real' entries, not drafts as far as I know. So your problem might just not have a solution in this case. If there was a canonical version of the entry you could use that, but since you mentioned your entries are only drafts ... not sure if this will work. What problem are you trying to solve here, anyway? Maybe there's a better solution?
    – MoritzLost
    Sep 24 at 13:48

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.