如何解决自定义WordPress循环中疑似内存问题?

时间:2015-05-25 作者:ban-geoengineering

我写了一个插件,添加了一个“你从哪里听说我们的?”向WooCommerce结帐页面提问,并在wp管理页面中显示结果(作为简单的水平条形图)。

这个插件工作得很好,但自从我写它以来,有些插件已经停止工作了——似乎是因为内存问题。

在我的wp配置中。php文件,我有。。。define(\'WP_MEMORY_LIMIT\', \'128M\');...我也试过了256MB, 512MB1G - 但这些都不能解决问题。

phpinfo() 报告amemory_limit 属于1G - 所以这看起来不错。

下面是我的插件的函数,PHP似乎放弃了它:

function get_customer_sources() {

    $args = array(
        \'post_type\' => \'shop_order\',
        \'post_status\' => \'publish\',
        \'posts_per_page\' => -1,
        \'tax_query\' => array(
            array(
                \'taxonomy\' => \'shop_order_status\',
                \'field\' => \'slug\',
                \'terms\' => array(\'processing\', \'completed\', \'cancelled\', \'failed\', \'refunded\')
            )
        )
    );

    //$custom_posts = new WP_Query($args);
    global $post; // required
    $custom_posts = get_posts($args);

    $all_sources = array(); //The return array
    echo "<h1>START</h1>";

    //while ($custom_posts->have_posts()) : $custom_posts->the_post();
    //if ( $custom_posts->have_posts() ) : while ( $custom_posts->have_posts() ) : $custom_posts->the_post();
    foreach($custom_posts as $post) : setup_postdata($post);


        //echo "<h2>A</h2>";

        $order_id = $post->ID;

        //echo "<h3>Order ID: $order_id</h3>";

        if ( get_post_meta($order_id, \'Where did you hear about us\', true) ) {

            $source = get_post_meta($order_id, \'Where did you hear about us\', true);

            //echo \'<h4>Order ID: \' . $order_id . \': \' . $source . \'</h4>\';

            // Fix the "Vegan event" vs "Vegan Event" problem
            $source = ucfirst(strtolower($source));

            // Add the source to the return array
            if (array_key_exists($source, $all_sources)) {
                // Increment existing value
                $num = $all_sources[$source];
                $all_sources[$source] = $num + 1;
            }
            else {
                // Add value
                $all_sources[$source] = 1;
            }

            //echo \'<h4>Num sources: \' . count($all_sources) . \'</h4>\';

        }

        //echo "<h2>B</h2>";

    //endwhile;
    //endwhile; endif;
    endforeach;

    echo "<h1>END</h1>";

    return $all_sources;
}`
我想可能有一些糟糕的数据把事情搞砸了,所以我改变了。。。

if ( get_post_meta($order_id, \'Where did you hear about us\', true) ) {

...行到。。。

if ( $order_id < 5000 && get_post_meta($order_id, \'Where did you hear about us\', true) ) {

...而且效果很好。

接下来,我把那行改成。。。

if ( $order_id >= 5000 && get_post_meta($order_id, \'Where did you hear about us\', true) ) {

...它仍然有效。

但没有5000 条件下,脚本就爆炸了。(我知道这是因为<h1>END</h1> 未输出。)

那么,我的代码有什么问题和/或如何解决方法不完整的问题?例如,在内存方面是否可以更有效地编写它?还是有更好的方法?(您将从评论中看到,我已经尝试使用WP_Query, 但我得到了同样的结果。)

注意-查询返回了大约10000个项目。

提前谢谢。

1 个回复
最合适的回答,由SO网友:TheDeadMedic 整理而成

查询返回了大约10000个项目。

这就是你的问题所在。无论你在循环中做什么,WordPress仍然在加载10,000 将对象发布到内存中。

对其进行批处理,并在查询参数中添加一些魔力:

$args = array(
    \'fields\'         => \'ids\', // MAGIC! Just get an array of id\'s, no objects committed to memory
    \'posts_per_page\' => 500,   // Batch size: big enough to reduce meta queries, small enough not to hammer memory
    \'post_type\'      => \'shop_order\',
    \'post_status\'    => \'publish\',
    \'tax_query\'      => array(
        array(
            \'taxonomy\' => \'shop_order_status\',
            \'field\' => \'slug\',
            \'terms\' => array( \'processing\', \'completed\', \'cancelled\', \'failed\', \'refunded\' ),
        )
    )
);

$query = new WP_Query;
$paged = 1;
$count = 0;
$total = null;

do {
    $args[\'no_found_rows\'] = isset( $total ); // No need to SQL_CALC_FOUND_ROWS on subsequent iterations
    $args[\'paged\'] = $paged++;

    $post_ids = $query->query( $args );
    update_postmeta_cache( $post_ids ); // Get all meta for this group of posts

    if ( ! isset( $total ) )
        $total = $query->found_posts;

    $count += $query->post_count;

    foreach ( $post_ids as $post_id ) {
        $source = get_post_meta( $post_id, \'Where did you hear about us\', true );

        // Do your stuff here



        // Wipe this post\'s meta from memory
        wp_cache_delete( $post_id, \'post_meta\' );
    }

} while ( $count < $total );

结束

相关推荐

Loop for sticky posts

我用过Justin Tadlock\'s 关于如何创建仅包含粘性帖子的循环的教程。代码大致如下所示:$sticky = get_option( \'sticky_posts\' ); rsort( $sticky ); $sticky = array_slice( $sticky, 0, 2 ); query_posts( array( \'post__in\' => $sticky, \'caller_get_posts\' => 1 ) ); 根据教程,我