We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 44922
    • 131 Posts
    Hi All,
    We've got a bunch of users at member level, and are wanting to loop through all the user profiles and run an "if" statement to return stuff depending on the user data.

    We are using:
    $profiles = $modx->getCollection('modUserProfile');
    foreach ($profiles as $profile) {
    then some if clause.
    The loop get part way through, then stops. It doesn't pull all the active profiles.

    We've got around 1000 user profiles, about half of which are active. My questions are:
    1) Presumably the above code only pulls active users?
    2) Is there a fixed limit to the amount of profiles we can loop with getCollection, or else are we beyond the number of profiles by which it's sensible to use this code? Or is it something else - rogue character in a profile etc.

    Thanks
      • 3749
      • 24,544 Posts
      There's no limit, but the default timeout for PHP is 30 seconds, so you may be hitting that.

      Your code pulls all users, not just active ones. Getting profiles for just the active users is tricky because the 'active' field is not in the modUserProfile.

      This should be close (untested):


      $c = $modx->newQuery('modUser);
      $c->where(array(
          'modUser.active' => '1',
      ));
      $users = $modx->getCollectionGraph('modUser', '{"Profile":{}}', $c);
      
      foreach ($users as $user) {
          $profile = $user->Profile;
      
          $username = $user->get('username');
          $email = $profile->get('email');
      }


      If there are other selection criteria, you can cut the processing time by adding them to the where array.

      Feel free to post your code. We may see other ways to make it more efficient.
        Did I help you? Buy me a beer
        Get my Book: MODX:The Official Guide
        MODX info for everyone: http://bobsguides.com/modx.html
        My MODX Extras
        Bob's Guides is now hosted at A2 MODX Hosting
        • 44922
        • 131 Posts
        Hi Bob, that's really helpful.
        We're using extended fields to match criteria in a " foreach -> if " situation. "For each" user, if this is true, then do this.

        From what you say, as this database is going to get bigger and bigger, in the future we may run into a PHP timeout again? Could we add another "->where(array)" for extended field criteria after your line 5 above?

        Also "Profile" in line five - we don't need to use 'modUserProfile' here?

        Thanks.
          • 3749
          • 24,544 Posts
          '$user->Profile' should be the variable set by getCollectionGraph() (based on the second argument).

          Using extended fields as a search criteria is quite slow and tricky because the extended fields are stored as a single JSON string containing all the data. There's also no good way to sort the results based on an extended field.

          There are two possible solutions, and if the database will become large, you really should use one of them.

          One is to store the data in other user profile text fields that you're not using (e.g., comment, phone, mobilephone, address, city, state, zip, fax, photo, website). You have to be careful about the maximum size of each field. This is kind of a hack, and it's a pain because the fields will all have the wrong names and you have to remember which is which. It's really only useful if you need a very small number of data fields, you're sure you won't be adding more, and you have enough unused profile fields.

          The more robust method (though a little more work to set up) is to use ClassExtender to extend the user object. This gives you unlimited fields with the correct names and very fast searching and sorting. In this case, your getCollectionGraph() call will be different. I'd suggest adding an 'active' field that mirrors the 'active' field of the modUser object to the custom fields (and username, if you need that too). That way, you won't have to access the modUser table at all and the queries will be faster. For even more speed, you could also mirror any fields you need from the modUserProfile object. That way you could just query the custom table with getCollection(), which is faster than getCollectionGraph(). You should be able to get all the users you need with a single query and use toArray() on them to set your placeholders.
            Did I help you? Buy me a beer
            Get my Book: MODX:The Official Guide
            MODX info for everyone: http://bobsguides.com/modx.html
            My MODX Extras
            Bob's Guides is now hosted at A2 MODX Hosting