2

I have a custom plugin that's saving an entry successfully. While saving the entry I'm setting our "merchant" field (an entries field, limit=1) like so:

<?php
# ...
$entry = newEntryModel();
# set the sectionId, typeId, authorId, and some other fields...
$entry->getContent()->merchant = (isset($data['merchant']) ? [$data['merchant']->id] : null; // $data['merchant'] is an EntryModel

This appears to be fine in the CP. I can see and edit the related entry.

However later in the application I have to update this entry and when updating the entry, I'm only updating a single field. While debugging the EntryModel that I'm trying to save I see that if I var_dump $entry->merchant I get an ElementCriteriaModel yet when I dump $entry->getContent->merchant I get 'null'.

My log shows the following error:

2014/10/31 18:25:46 [warning] [application] Craft\ContentModel->merchant failed validation: Merchant cannot be blank.

According to this tweet it seems like dumping $entry->getContent()->merchant should be returning a ContentModel instead of null.

Any ideas?

EDIT: I've confirmed that everything works as expected if the field is NOT marked as required. However, this can't really be a solution - I need to make sure that the client cannot leave this field blank.

4

getContent() will return the element’s ContentModel, NOT getContent()->merchant, which is just an attribute of the ContentModel—sorry for the confusion.

I’ve just posted a separate Q&A fully explaining what the ContentModel is used for here:

What is getContent() / the ContentModel, and how do I use it to get and set custom field values?

What you are experiencing is actually a slight bug in Craft’s validation logic. Relational fields have a feature where their data is not actually required to be in POST when saving an entry. If that’s the case (if their value in the ContentModel ends up just being null), then they will simply not make any changes to the element’s relationships - the field value will be left untouched.

However the ContentModel is not aware of that feature, and it’s the ContentModel that is currently in charge of enforcing Required Field validation. So, when it gets to your relational field, and finds that its value is null, it gives you a validation error rather than letting it slide.

So, you have two workaround options, if you want to keep the data the same, but need the field to be required:

  1. You can actually set the value based on the current value:

    $entry->setContentFromPost(array(
        // ...
        'merchant' => $entry->merchant->ids(),
    ));
    
    craft()->entries->saveEntry($entry);
    
  2. If all you’re doing is changing custom field values (nothing entry-specific) and you’re comfortable skipping custom field validation altogether, you can just call ContentService::saveContent() directly, and pass in false to its second argument which tells it to skip validation:

    $entry->setContentFromPost(array(
        // ...
        'merchant' => null, // Tells the relational field to keep the old value
    ));
    
    craft()->content->saveContent($entry, false);
    
  • Just experienced the same behavior, the workaround does the job thanks! are there any developments on this behavior – Jacob Apr 21 '16 at 8:16
  • 2
    @Jacob Yes we’ve made this not-awkward in Craft 3 :) – Brandon Kelly Apr 21 '16 at 13:51

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.