Answers.Body: <p>Here's another way to avoid the "saveEntry" infinite loop. I like to have a method in a service class that my plugin that can reuse over and over again to update entry values. As you can see, we avoid unnecessary statics and clutter in the plugin init() method.
  The main thing to point out is the use of "saveElement()" instead of "saveEntry()" which is the key to not triggering the saveEntry event endlessly.</p>
  
  <p>From the main plugin file:</p>
  
  <pre><code>/**
   * Plugin Init
   */
  public function init()
  {
      parent::init();
  
      // triggers
      craft()-&gt;on('entries.saveEntry', array($this, '_processUsersToNotify'));
  }
  
  /**
   * Process Users To Notify
   *
   * @param Event $event
   */
  public function _processUsersToNotify(Event $event)
  {
      $entry = $event-&gt;params['entry']-&gt;attributes;
  
      $entryData = [
          'fieldSlug1' =&gt; 'lorem ipsum',
          'usersToNotify' =&gt; [1,2,3,4,5],
      ];
  
      // using a service method (replace pluginName/serviceName accordingly)
      craft()-&gt;pluginName_serviceName-&gt;updateEntry($entry['id'], $entryData);
  }
  </code></pre>
  
  <p>Then in your service file:</p>
  
  <pre><code>/**
   * Update Entry Data
   */
  public function updateEntry($entryId, $data)
  {
      // placeholder for phase 2 feature
      $entry = craft()-&gt;entries-&gt;getEntryById($entryId);
  
      // set attrs
      $entry-&gt;getContent()-&gt;setAttributes($data);
  
      if ($entry-&gt;validate())
      {
          craft()-&gt;elements-&gt;saveElement($entry);
      }
      else
      {
          return $entry-&gt;getErrors();
      }
  
      return true;
  }
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-10-03T18:19:33.017Z
Answers.LastActivityDate: 2016-10-03T18:19:33.017Z
Answers.UserDisplayName: Jarrett Barnett
Answers.Body: <p>You've created an endless loop with calling <code>saveEntry</code> within the <code>entries.saveEntry</code> event listener. You can fix it with implementing a static variable.</p>
  
  <pre><code>craft()-&gt;on('entries.saveEntry', function(Event $event) {
      static $recursionLevel = 0;
  
      if ($recursionLevel == 0) {
          $recursionLevel++;
  
          // `saveEntry` in `addAnotherUserToNotify` triggers another
          // `entries.saveEntry` event
      }
  });
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-03-30T08:56:55.673Z
Answers.LastActivityDate: 2016-03-30T08:56:55.673Z
Answers.UserDisplayName: carlcs
Body: <p>I'm building a plugin which needs to add users to a users-type field when they edit the entry on the front-end. It works well when the post is created, adding the original author to the field, and again when the same user edits the post. However, when another user edits the post everything comes to a standstill for a minute and users are taken not to the landing page, but to a page containing nothing other than a "1". Checking the back-end, it has added the second user to the field, though.</p>
  
  <p>Can anyone suggest to me from the code below why adding a second (haven't tested any more than that yet) user brings things the server to its knees?</p>
  
  <pre><code>public function init()
  {
      parent::init();
  
      // ON SAVE ENTRY
      craft()-&gt;on('entries.saveEntry', function(Event $event) {
  
          $entry = $event-&gt;params['entry'];
          $user = craft()-&gt;userSession-&gt;getUser();
          $notifyMe = craft()-&gt;request-&gt;getPost('notifyme');          
  
          // CHECK THIS IS THE FORUM SECTION
          if ($entry-&gt;sectionId == 16) {
              craft()-&gt;notifier-&gt;addAnotherUserToNotify($entry, $user, $notifyMe);
          }           
      });
  }
  </code></pre>
  
  <p>And here is the function:</p>
  
  <pre><code>// ADD ANOTHER USER TO A POST'S NOTIFICATION LIST
  public function addAnotherUserToNotify($entry, $user, $notifyMe) 
  {
      if ($notifyMe == "yes") {
  
          // GET IDs OF USERS ALREADY LISTED TO BE NOTIFIED
          $usersToNotify = $entry-&gt;usersToNotify-&gt;ids();
          if ( ! in_array( $user-&gt;id, $usersToNotify ) ) {
              // ADD THE CURRENT USER TO THE ARRAY OF USERS TO BE NOTIFIED
              $usersToNotify[] = $user-&gt;id;
          }           
  
          // UPDATE THE ENTRY'S FIELD WITH THIS UPDATED ARRAY
          $entry-&gt;getContent()-&gt;setAttribute('usersToNotify', $usersToNotify);
  
          // SAVE ENTRY
          craft()-&gt;entries-&gt;saveEntry($entry);
  
      }
  
  }
  </code></pre>
  
  <p>The code is inspired by <a href="https://craftcms.stackexchange.com/questions/13032/update-user-field-type-for-entry-in-plugin">Update User &quot;Field Type&quot; for Entry in Plugin</a></p>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-03-30T08:38:16.637Z
Comments.Text: Can you post the (relevant) code from that `addAnotherUserToNotify` method, my guess is you've created an endless loop with calling `saveEntry` within the `entries.saveEntry` event listener.
Comments.UserDisplayName: carlcs
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-03-30T08:44:31.050Z
Comments.Text: Sorry, I thought I'd added that but lost it while faffing with the formatting. Added.
Comments.UserDisplayName: Clive Portman
Tags: <plugin-development><users>
Title: Adding second user to user field in plugin brings server to its knees
ThreadText: # Adding second user to user field in plugin brings server to its knees
  
  (Asked by: username_0 on 2016-03-30)
  
  I'm building a plugin which needs to add users to a users-type field when they edit the entry on the front-end. It works well when the post is created, adding the original author to the field, and again when the same user edits the post. However, when another user edits the post everything comes to a standstill for a minute and users are taken not to the landing page, but to a page containing nothing other than a "1". Checking the back-end, it has added the second user to the field, though.
  
  Can anyone suggest to me from the code below why adding a second (haven't tested any more than that yet) user brings things the server to its knees?
  
  ```
  public function init()
  {
      parent::init();
  
      // ON SAVE ENTRY
      craft()->on('entries.saveEntry', function(Event $event) {
  
          $entry = $event->params['entry'];
          $user = craft()->userSession->getUser();
          $notifyMe = craft()->request->getPost('notifyme');          
  
          // CHECK THIS IS THE FORUM SECTION
          if ($entry->sectionId == 16) {
              craft()->notifier->addAnotherUserToNotify($entry, $user, $notifyMe);
          }           
      });
  }
  
  ```
  
  And here is the function:
  
  ```
  // ADD ANOTHER USER TO A POST'S NOTIFICATION LIST
  public function addAnotherUserToNotify($entry, $user, $notifyMe) 
  {
      if ($notifyMe == "yes") {
  
          // GET IDs OF USERS ALREADY LISTED TO BE NOTIFIED
          $usersToNotify = $entry->usersToNotify->ids();
          if ( ! in_array( $user->id, $usersToNotify ) ) {
              // ADD THE CURRENT USER TO THE ARRAY OF USERS TO BE NOTIFIED
              $usersToNotify[] = $user->id;
          }           
  
          // UPDATE THE ENTRY'S FIELD WITH THIS UPDATED ARRAY
          $entry->getContent()->setAttribute('usersToNotify', $usersToNotify);
  
          // SAVE ENTRY
          craft()->entries->saveEntry($entry);
  
      }
  
  }
  
  ```
  
  The code is inspired by [Update User "Field Type" for Entry in Plugin](https://craftcms.stackexchange.com/questions/13032/update-user-field-type-for-entry-in-plugin)
  
  **Tags:** plugin-development, users
  
  > **Comments:**
  > **username_1**: Can you post the (relevant) code from that `addAnotherUserToNotify` method, my guess is you've created an endless loop with calling `saveEntry` within the `entries.saveEntry` event listener.  
  > **username_0**: Sorry, I thought I'd added that but lost it while faffing with the formatting. Added.  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_1 on 2016-03-30. Score: 5 | Accepted answer
  
  You've created an endless loop with calling `saveEntry` within the `entries.saveEntry` event listener. You can fix it with implementing a static variable.
  
  ```
  craft()->on('entries.saveEntry', function(Event $event) {
      static $recursionLevel = 0;
  
      if ($recursionLevel == 0) {
          $recursionLevel++;
  
          // `saveEntry` in `addAnotherUserToNotify` triggers another
          // `entries.saveEntry` event
      }
  });
  
  ```
  
  
  ---
  
  ### Answer by username_2 on 2016-10-03. Score: 1
  
  Here's another way to avoid the "saveEntry" infinite loop. I like to have a method in a service class that my plugin that can reuse over and over again to update entry values. As you can see, we avoid unnecessary statics and clutter in the plugin init() method.
  The main thing to point out is the use of "saveElement()" instead of "saveEntry()" which is the key to not triggering the saveEntry event endlessly.
  
  From the main plugin file:
  
  ```
  /**
   * Plugin Init
   */
  public function init()
  {
      parent::init();
  
      // triggers
      craft()->on('entries.saveEntry', array($this, '_processUsersToNotify'));
  }
  
  /**
   * Process Users To Notify
   *
   * @param Event $event
   */
  public function _processUsersToNotify(Event $event)
  {
      $entry = $event->params['entry']->attributes;
  
      $entryData = [
          'fieldSlug1' => 'lorem ipsum',
          'usersToNotify' => [1,2,3,4,5],
      ];
  
      // using a service method (replace pluginName/serviceName accordingly)
      craft()->pluginName_serviceName->updateEntry($entry['id'], $entryData);
  }
  
  ```
  
  Then in your service file:
  
  ```
  /**
   * Update Entry Data
   */
  public function updateEntry($entryId, $data)
  {
      // placeholder for phase 2 feature
      $entry = craft()->entries->getEntryById($entryId);
  
      // set attrs
      $entry->getContent()->setAttributes($data);
  
      if ($entry->validate())
      {
          craft()->elements->saveElement($entry);
      }
      else
      {
          return $entry->getErrors();
      }
  
      return true;
  }
  
  ```
  
  
  ---
  
  