Answers.Body: <p>You can check if an element is valid by calling <a href="https://www.yiiframework.com/doc/api/2.0/yii-base-model#validate()-detail" rel="nofollow noreferrer">Entry::validate()</a> yourself. The problem is that if you do that inside the <code>EVENT_BEFORE_VALIDATE</code> hook, it <em>might</em> cause an infinite loop (not sure if Yii2/Craft are smart enough to detect this, may be worth testing). However, it should work fine if you execute the validation in an <code>EVENT_BEFORE_SAVE</code> hook:</p>
  <pre class="lang-php prettyprint-override"><code>Event::on(
      Entry::class,
      Element::EVENT_BEFORE_SAVE,
      function (ModelEvent $e) {
          $entry = $e-&gt;sender;
          // bail if the entry is not valid
          if (!$entry-&gt;validate()) return;
  
          // now we can safely execute the API call since the entry is valid
      },
  );
  </code></pre>
  <p>If the validation fails, you don't have to do anything else because the Craft will prevent saving the entry anyway. If the validation succeeds, you know the regular fields are valid and can continue with your API call. If something goes wrong there, you can set <code>$e-&gt;isValid = false</code> and it will prevent the entry from saving, same as in the <code>EVENT_BEFORE_VALIDATE</code> hook.</p>
  <p>Now there might be some edge cases, for example if you have another hook modifying the entry to make it valid AFTER your hook has run. But I doubt that will make a difference in practical terms.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-06-17T08:42:36.260Z
Answers.LastActivityDate: 2021-06-17T08:42:36.260Z
Answers.UserDisplayName: MoritzLost
Body: <p>I am trying to validate entries on Save in a Module.</p>
  <p>My specific use case requires that the Entry validation - on failure to validate will return user to form with field errors.</p>
  <p>On successful validation I want to use that information to call an API with the field information and if all goes well I want to save - otherwise (e.g. API error) - I want to cause validation failure and show specific errors on the form.</p>
  <p>From My understanding: the events occur in the following order:</p>
  <p>EVENT_BEFORE_SAVE, EVENT_BEFORE_VALIDATE, EVENT_AFTER_VALIDATE, EVENT_AFTER_SAVE</p>
  <p>I know I can do this:</p>
  <pre><code>    Event::on(
          Entry::class,
          Entry::EVENT_BEFORE_VALIDATE,
          function(ModelEvent $event) {
              $entry = $event-&gt;sender;
              //if send to api failure
              $entry-&gt;addError('field','api failed');
              $event-&gt;isValid=false;
  
          }
      );
  </code></pre>
  <p>It allows me to invalidate the save but - It does so before the regular fields are validated.
  My desire here is that I can protect some bad inputs to the API using crafts validation features and then send to API and then act upon its result.</p>
  <p>From what I have seen - EVENT_AFTER_VALIDATE always runs even if the field validation failed.</p>
  <p>So It made sense to me that I could check $event-&gt;isValid in EVENT_AFTER_VALIDATE so my API hit would only happen on successful validate</p>
  <p>I have discovered that EVENT_AFTER_VALIDATE is receiving an Event instead of a ModelEvent
  Which means $event-&gt;isValid cannot be used to invalidate the save or check if the validation was successful. I've tried switching this around to no avail.</p>
  <p>I seem to be able to use $entry-&gt;addError() to invalidate the save.
  I'm just missing how to find out how the regular validation went..</p>
  <pre><code>    Event::on(
          Entry::class,
          Entry::EVENT_AFTER_VALIDATE,
          function(Event $event) {
              $entry = $event-&gt;sender;
              //if ($event-&gt;isValid) {
                  //if send to api failure
                  $entry-&gt;addError('field','api failed');
              //}
          }
      );
  </code></pre>
  
Tags: <events><modules><api>
Title: Craftcms 3 Module - API call validation (on EVENT_BEFORE_SAVE, EVENT_BEFORE_VALIDATE, EVENT_AFTER_VALIDATE, EVENT_AFTER_SAVE)
ThreadText: # Craftcms 3 Module - API call validation (on EVENT_BEFORE_SAVE, EVENT_BEFORE_VALIDATE, EVENT_AFTER_VALIDATE, EVENT_AFTER_SAVE)
  
  (Asked by: username_0 on 2021-06-17)
  
  I am trying to validate entries on Save in a Module.
  
  My specific use case requires that the Entry validation - on failure to validate will return user to form with field errors.
  
  On successful validation I want to use that information to call an API with the field information and if all goes well I want to save - otherwise (e.g. API error) - I want to cause validation failure and show specific errors on the form.
  
  From My understanding: the events occur in the following order:
  
  EVENT\_BEFORE\_SAVE, EVENT\_BEFORE\_VALIDATE, EVENT\_AFTER\_VALIDATE, EVENT\_AFTER\_SAVE
  
  I know I can do this:
  
  ```
      Event::on(
          Entry::class,
          Entry::EVENT_BEFORE_VALIDATE,
          function(ModelEvent $event) {
              $entry = $event->sender;
              //if send to api failure
              $entry->addError('field','api failed');
              $event->isValid=false;
  
          }
      );
  
  ```
  
  It allows me to invalidate the save but - It does so before the regular fields are validated.
  My desire here is that I can protect some bad inputs to the API using crafts validation features and then send to API and then act upon its result.
  
  From what I have seen - EVENT\_AFTER\_VALIDATE always runs even if the field validation failed.
  
  So It made sense to me that I could check $event->isValid in EVENT\_AFTER\_VALIDATE so my API hit would only happen on successful validate
  
  I have discovered that EVENT\_AFTER\_VALIDATE is receiving an Event instead of a ModelEvent
  Which means $event->isValid cannot be used to invalidate the save or check if the validation was successful. I've tried switching this around to no avail.
  
  I seem to be able to use $entry->addError() to invalidate the save.
  I'm just missing how to find out how the regular validation went..
  
  ```
      Event::on(
          Entry::class,
          Entry::EVENT_AFTER_VALIDATE,
          function(Event $event) {
              $entry = $event->sender;
              //if ($event->isValid) {
                  //if send to api failure
                  $entry->addError('field','api failed');
              //}
          }
      );
  
  ```
  
  **Tags:** events, modules, api
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2021-06-17. Score: 2 | Accepted answer
  
  You can check if an element is valid by calling [Entry::validate()](https://www.yiiframework.com/doc/api/2.0/yii-base-model#validate()-detail) yourself. The problem is that if you do that inside the `EVENT_BEFORE_VALIDATE` hook, it *might* cause an infinite loop (not sure if Yii2/Craft are smart enough to detect this, may be worth testing). However, it should work fine if you execute the validation in an `EVENT_BEFORE_SAVE` hook:
  
  ```php
  Event::on(
      Entry::class,
      Element::EVENT_BEFORE_SAVE,
      function (ModelEvent $e) {
          $entry = $e->sender;
          // bail if the entry is not valid
          if (!$entry->validate()) return;
  
          // now we can safely execute the API call since the entry is valid
      },
  );
  
  ```
  
  If the validation fails, you don't have to do anything else because the Craft will prevent saving the entry anyway. If the validation succeeds, you know the regular fields are valid and can continue with your API call. If something goes wrong there, you can set `$e->isValid = false` and it will prevent the entry from saving, same as in the `EVENT_BEFORE_VALIDATE` hook.
  
  Now there might be some edge cases, for example if you have another hook modifying the entry to make it valid AFTER your hook has run. But I doubt that will make a difference in practical terms.
  
  
  ---
  
  