我写了一个插件,添加了一个“你从哪里听说我们的?”向WooCommerce结帐页面提问,并在wp管理页面中显示结果(作为简单的水平条形图)。
这个插件工作得很好,但自从我写它以来,有些插件已经停止工作了——似乎是因为内存问题。
在我的wp配置中。php文件,我有。。。define(\'WP_MEMORY_LIMIT\', \'128M\');
...我也试过了256MB
, 512MB
和1G
- 但这些都不能解决问题。
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个项目。
提前谢谢。
最合适的回答,由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 );