Utility code - foreach times out

In several code examples, Jason suggests the construct:
foreach(get_users(‘role=subscriber’) as $user) {…

This works great on a couple of sites with modest numbers of members. However, on a larger site with just over 6000 “subscriber” level members, it apparently times out. No results, no error messages. Maybe there’s a way to reduce that request to a subset of “subscribers”? Suggestions?

I’m pretty sure that it isn’t timing out but is running out of memory. That is a known issue with foreach loops in PHP. In principle, I can think of four ways to address this:

  1. Increase the amount of memory available.
  2. Store a variable before the foreach, so that you’d write something like
    $users = get_users( 'role = subscriber' ); foreach( $users as $user ) {
  3. Unset the variable after you have finished with it, i.e.
    } unset( $users );
  4. Use an alternative to the foreach loop.

I’d try all of 1 to 3 together, but my guess is they won’t be enough. If that proves to be true, I’d suggest you Google php foreach alternative to see which alternative would best suit whatever you are attempting to do.

You’re right Tim: it’s memory.

Trying suggestions 2 and 3 together got PHP to produce a “memory exhausted” message, which occurred BTW from the SQL query inside wp-includes/wp-db.php.

Eureka! ini-set(memory_limit, “160M”) did the rest.

THANK YOU!

Great! That’s useful to know and quite reassuring, because I feared it would demand much more memory than that.

Once beyond that hurdle, another one popped up. But, it’s manageable.

The little plug-in is intended to remove inactive free members from a membership site that currently has about 5500 free members. Of those, about 2200 haven’t visited in a year and we’re pruning.

The script now handles the number of users with ease. You helped me get to the point, of listing all the candidates for deletion. Adding the actual wp_delete_user line extended the run time. So, it runs for 30 seconds, does part of the job and we run it again, whittling away about 250 users each pass… That’s fine for now and I appreciate your help.

You can set a “wp_cron” cronjob to run with 30 sec incremental delay and to delete 200 users. This way yuor “foreach” will find all of them, but the cronjob will delete them in batches of 200, and hidden (as a separate process in memory), so you will not experience any timeout.

Still I think if you run that (existing) script each day, it will not need to delete 2000 users daily and will not be timeout, so as first run it’s OK to “push” it 5 times…

Exactly. After the original cleanup, a daily cron will keep it clean.

Thanks Krum. Enjoy your day,