6

I was running into memory issues with this:

get_posts( array( 'posts_per_page' => '-1', 'post_type' => array( 'product', 'product_variation' ) )

(there are thousands of results) just trying to get a list of all post IDs.

The below code grabs 10 products at a time, to hopefully avoid any memory limits. It seems to work OK but there is probably a more elegant solution.

https://gist.github.com/dtbaker/acd15e542d98bff68034

$product_page = 1;
$product_per_page = 10;
$product_query = new WP_Query( array(
    'posts_per_page' => $product_per_page,
    'paged'          => $product_page,
    'post_type'      => array( 'product', 'product_variation' ),
) );
$product_ids = array();
while($product_query->have_posts() ) {
    $product_result = $product_query->next_post();
    if(!$product_result){
        // get the next lot of results.
        $product_page++;
        $product_query = new WP_Query( array(
            'posts_per_page' => $product_per_page,
            'paged'          => $product_page,
            'post_type'      => array( 'product', 'product_variation' ),
        ) );
    }else{
        $product_ids[] = $product_result->ID;
    }
}
print_r($product_ids);

I would love to know if there's a better way to do this "10 products at a time" query. Thanks!

10

Use the fields argument to grab just the ID - will save you a ton of memory ;)

$product_ids = get_posts(
    array(
        'posts_per_page' => -1,
        'post_type'      => array( 'product', 'product_variation' ),
        'fields'         => 'ids',
    )
);
  • Exactly what I was after, thanks! I didn't know this was possible. – dtbaker Aug 27 '14 at 5:27
1

Running a no LIMIT query is likely the cause of your memory issues.

To get a list of all the post IDs we must first know how many posts exists. Since MySQL knows this already, we can just ask:

$product_query = new WP_Query( array(
    'posts_per_page' => 1,
    'post_type'      => array( 'product', 'product_variation' ),
    'post_status'    => 'publish', // explicitly setting post_status helps memory usage
    'fields'         => 'ids',
) );

$total_products_count = $products->found_posts;

This query will do the least possible to get the total number of posts.

With this knowledge we can grab a list of all the IDs using the $total_products_count we found from the previous query:

$product_query = new WP_Query( array(
    'posts_per_page' => $total_products_count,
    'post_type'      => array( 'product', 'product_variation' ),
    'post_status'    => 'publish',
    'fields'         => 'ids',
    'no_found_rows'  => true, // to disable found_posts calculation
) );

$product_ids = $product_query->posts;
0

get_posts() and WP_Query() both shares the same way of Querying the database. I experienced the exact same issue even I used WP_Query() instead of get_posts(). The PHP memory ran out time to time. Then I figured out the issue.

The culprit was:

'posts_per_page' => '-1'

With a -1 there the query runs until it fetches each and every results matches to the query even that can be hundreds, thousands, or millions... and that's the major issue. Just limit your query to a number 10, 20, 100 but not an infinity (-1).

That will make the deal.

And additionally have a look at this WPSE thread.

  • Thanks! Yes in the above code I removed the -1 for posts_per_page and replaced it with a loop that grabbed 10 products at a time. Was just wondering if there's a better way to do the "10 products at a time" query. – dtbaker Aug 26 '14 at 4:47
  • better is what? $wpdb query = get_posts() = WP_Query(). Or you can write your own SQL query. Nothing else is present. :( – Mayeenul Islam Aug 26 '14 at 5:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.