<p>You could just setup a criteria model in your “categories” for-loop, prepared to query for the users related to that category. And then use the <code>total()</code> method to get the count.</p>

<pre class="lang-php prettyprint-override"><code>foreach($category as $interest) {
    $user_criteria = craft()-&gt;elements-&gt;getCriteria(ElementType::User);
    $user_criteria-&gt;relatedTo = $interest-&gt;id;
    $count = $user_criteria-&gt;total();

    $interestArray[$interest-&gt;title] = $count;
}
</code></pre>

<p>Using the <code>total()</code> method is a lot faster than <code>find()</code>, the underlaying SQL which is necessary to get the amount of rows performs better and Craft also doesn’t have to populate the Entry models with all the data.</p>

<p><em>(Not sure why @LukePearce deleted his answer, where he basically suggested to do the same thing.)</em></p>

CC BY-SA 3.0
2016-06-30T18:49:15.273Z
I re-read the question and thought it was asking for something different, I have now re-read again and realised I was correct... oops!
Luke Pearce
CC BY-SA 3.0
2016-07-04T09:57:19.063Z
@carlcs thanks for the reply and I can see this would wotk normally. The only thing is we are using a dynamic checkbox field for the user interests. This is created from the categories group. So there is no related category field being used directly. Is there a way to check the dynamic checkbox field for the $interests->id in the criteria?
Lettie
CC BY-SA 3.0
2016-07-04T10:02:27.103Z
@Lettie nope, a checkboxes field stores an array of IDs serialized as JSON, so there's no good way to use that data in a SQL query.
carlcs
CC BY-SA 3.0
2016-07-04T10:04:13.500Z
@carlcs yes sorry just read your previous post http://craftcms.stackexchange.com/questions/11991/how-to-return-entries-based-on-checkboxes-field-criteria cheers
Lettie
CC BY-SA 3.0
2016-06-30T17:27:32.760Z
2016-06-30T18:57:29.357Z
2016-06-30T18:57:29.357Z
carlcs
<p>Hi I have a plugin that loops through users to find out their interests. Counts the number of interests in total for each interest and displays this in a widget on the dashboard with the interest name and amount of users with that interest. The code I have works but fails with a max execution time and only pulls out minimal results for each interest. Is there a way to do this more efficiently so the script does not timeout. This is what I have so far but I'm sure looping through 20k+ users and checking each interest field to see if the category id is in it is highly inefficient. Cheers.</p>

<pre><code>public function getInterestRank()
{
    $criteria = craft()-&gt;elements-&gt;getCriteria(ElementType::Category);
    $criteria-&gt;group = 'interestTags';
    $category = $criteria-&gt;find();

    //Get all users
    $user_criteria = craft()-&gt;elements-&gt;getCriteria(ElementType::User);
    $users = $user_criteria-&gt;find();

    $interestArray = array();

    foreach($category as $interest)
    {
        $title = $interest['title'];
        $count = 0;

        foreach($users as $user)
        {
            if($user['interests']) {
                if(in_array($interest['id'], $user['interests']))
                {
                    $count = $count+1;
                }
            }
        }
        $interestArray[$title] = $count;
    }

    arsort($interestArray);
    return ($interestArray);
}
</code></pre>

<plugin-development><users><plugins>
Efficient way of looping through a large amount of users?
# Efficient way of looping through a large amount of users?

(Asked by: username_0 on 2016-06-30)

Hi I have a plugin that loops through users to find out their interests. Counts the number of interests in total for each interest and displays this in a widget on the dashboard with the interest name and amount of users with that interest. The code I have works but fails with a max execution time and only pulls out minimal results for each interest. Is there a way to do this more efficiently so the script does not timeout. This is what I have so far but I'm sure looping through 20k+ users and checking each interest field to see if the category id is in it is highly inefficient. Cheers.
public function getInterestRank()
{
    $criteria = craft()->elements->getCriteria(ElementType::Category);
    $criteria->group = 'interestTags';
    $category = $criteria->find();

    //Get all users
    $user_criteria = craft()->elements->getCriteria(ElementType::User);
    $users = $user_criteria->find();

    $interestArray = array();

    foreach($category as $interest)
    {
        $title = $interest['title'];
        $count = 0;

        foreach($users as $user)
        {
            if($user['interests']) {
                if(in_array($interest['id'], $user['interests']))
                {
                    $count = $count+1;
                }
            }
        }
        $interestArray[$title] = $count;
    }

    arsort($interestArray);
    return ($interestArray);
}

**Tags:** plugin-development, users, plugins


---

## 1 answers

### Answer by username_1 on 2016-06-30. Score: 3

You could just setup a criteria model in your “categories” for-loop, prepared to query for the users related to that category. And then use the total() method to get the count.
foreach($category as $interest) {
    $user_criteria = craft()->elements->getCriteria(ElementType::User);
    $user_criteria->relatedTo = $interest->id;
    $count = $user_criteria->total();

    $interestArray[$interest->title] = $count;
}

Using the total() method is a lot faster than find(), the underlaying SQL which is necessary to get the amount of rows performs better and Craft also doesn’t have to populate the Entry models with all the data.
(Not sure why @LukePearce deleted his answer, where he basically suggested to do the same thing.)

> **Comments:**
> **username_2**: I re-read the question and thought it was asking for something different, I have now re-read again and realised I was correct... oops!  
> **username_0**: @username_1 thanks for the reply and I can see this would wotk normally. The only thing is we are using a dynamic checkbox field for the user interests. This is created from the categories group. So there is no related category field being used directly. Is there a way to check the dynamic checkbox field for the $interests->id in the criteria?  
> **username_1**: @username_0 nope, a checkboxes field stores an array of IDs serialized as JSON, so there's no good way to use that data in a SQL query.  
> **username_0**: @username_1 yes sorry just read your previous post http://craftcms.stackexchange.com/questions/11991/how-to-return-entries-based-on-checkboxes-field-criteria cheers  

---

