2014-12-10 67 views
1

我已经制作了这个脚本,我运行了一个WP_Query(),它可以获得2,000条记录并且正在增长。我希望能够将这些结果写入CSV文件。当posts_per_page设置为300或更少的记录时,我有这个工作。如何优化csv脚本的wp_query?

如果我改变posts_per_page为-1,然后我得到这个错误:

Fatal error: Allowed memory size of 134217728 bytes exhausted 

我想知道,如果有,我可以在同一时间在同一时间发送300条记录到CSV文件,直到办法没有更多,然后触发文件下载?

或者也许可以将每行都流到CSV文件?在做fopencsv时管理内存的最佳方式是什么?

这是我现在有:

$export_query = array(
    'post_type' => 'videorepot', 
    'posts_per_page' => -1, 
    'status' => 'published', 
    'meta_query' => array(
     array(
      'key'  => 'agree', 
      'value' => 1, 
      'compare' => '=', 
     ), 
     array(
      'key'  => 'opt-in', 
      'value' => 1, 
      'compare' => '=', 
     ), 
     array(
      'key'  => 'status', 
      'value' => 'Video Ready', 
      'compare' => '=', 
     ), 
    ) 
); 

// Posts query 
$wp_query = new WP_Query($export_query); 
if ($wp_query->have_posts()) : 
    $list = array('Email,Photo1,Photo2,Photo3,VideoURL'); 
    while ($wp_query->have_posts()) : $wp_query->the_post(); 

     $postID = get_the_ID(); 

     $user_email = get_post_meta($postID, 'user_email', true); 
     $photo1 = get_post_meta($postID, 'photo1', true); 
     $photo2 = get_post_meta($postID, 'photo2', true); 
     $photo3 = get_post_meta($postID, 'photo3', true); 
     $videourl = get_post_meta($postID, 'video_file', true); 

     $list[] = $user_email.','.$photo1.','.$photo2.','.$photo3.','.$videourl; 

    endwhile; 
endif; 


// Output file stream 
$output_filename = 'export_' . strftime('%Y-%m-%d') . '.csv'; 
$output_handle = @fopen($output_filename, 'w'); 

header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
header('Content-Description: File Transfer'); 
header('Content-type: text/csv'); 
header('Content-Disposition: attachment; filename=' . $output_filename); 
header('Expires: 0'); 
header('Pragma: public'); 

foreach ($list as $line) { 

    // Add row to file 
    fputcsv($output_handle, explode(',', $line), ',', '"'); 

} 

// Close output file stream 
fclose($output_handle); 

// We're done! 
exit; 

更新#1 对于一些测试我删除写入资料转移到CSV文件中的脚本的一部分,所以我发现它真的我在这里查询的东西让它变得疯狂。我的自定义文章类型中可能有3000条记录。为什么这会让我的查询耗尽内存?

更新#2

,我决定走了不同的路线,因为我使用wp_query时仍然遇到内存问题。所以,我写了我的mySQL查询 - 你知道我从其他例子入侵它。这个查询运行得非常快,所以我想我会有更好的运气。

我有一个新的问题,因为这与meta_key/meta_values有关。目前,我在查询中使用SELECT *,但我不想选择所有内容。我只需要数据库中的大约5个字段。我想要的这些字段中的一些是meta_key/meta_value。有没有一种方法可以指定这些meta_keys,所以当我导出表格时,我只能得到5列结果?

我的查询看起来像现在这样:

$values = mysql_query("SELECT * FROM wp_posts 
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id) 
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id) 
INNER JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id) WHERE 1=1 
AND ((post_date >= '2014-11-03 00:00:00' AND post_date <= '2014-12-31 23:59:59')) 
AND wp_posts.post_type = 'videorepot' 
AND (wp_posts.post_status = 'publish') 
AND ((wp_postmeta.meta_key = 'agree' AND CAST(wp_postmeta.meta_value AS CHAR) = '1') 
AND (mt1.meta_key = 'opt-in' AND CAST(mt1.meta_value AS CHAR) = '1') 
AND (mt2.meta_key = 'status' AND CAST(mt2.meta_value AS CHAR) = 'Video Ready')) 
GROUP BY wp_posts.ID 
ORDER BY wp_posts.post_date DESC 
LIMIT 0,20"); 

现在我设置的限制20,但我已经设置为0,9999极限测试,它的运行速度非常快,phpMyAdmin的。上面的查询给我约1282个结果,当我没有设置限制。

更新#3

我已经发布了一个解决方案,我的答案。感谢您的帮助David。

+0

增加php内存...或者添加后期元来表示你已经下载并设置最大结果为200左右(不包括下载) – David 2014-12-11 00:59:00

+0

我宁愿不只是增加PHP内存。我有兴趣学习在这种情况下正确的PHP技术来管理内存。我会暂时尝试这个。另外根据这个错误,我可以使用134 MB的内存,我认为这是相当高的。 事情是我想每次点击一个链接时导出完整的数据库,所以没有必要将项目设置为正在下载。尽管如此,感谢您的评论。 – Robbiegod 2014-12-11 02:34:05

+0

是真实的,但你没有134 MB与...一起工作,但取消了你的循环后使用wp查询,而不是foreach(foreach再次创建另一个副本,所以你实际上有3个副本),然后取消设置$ list数组,当你循环它。 – David 2014-12-11 09:26:19

回答

0

我想到了一个很好的解决方案。这适用于我,我不必增加PHP内存或类似的东西。

这是未经编辑的最终脚本。请记住我正在使用的mysql查询使用日期范围和3个meta_keys从我们的数据库获取数据的一个子集。我收到大约1290个全部写入CSV文件的结果。 (感谢大卫的帮助。)

$path = $_SERVER['DOCUMENT_ROOT']; 

include_once $path . '/wp-load.php'; 

// SET UP DB VARS 
$host = DB_HOST; 
$user = DB_USER; 
$pass = DB_PASSWORD; 
$db = DB_NAME; 


// CONNECT TO DB 
$link = mysql_connect($host, $user, $pass) or die("Can not connect." . mysql_error()); 
mysql_select_db($db) or die("Can not connect."); 

$mycolums = array('Email,Photo1,Photo2,Photo3,VideoURL'); 
foreach ($mycolums as $column) { 
    $csv_output = $column.", "; 
} 
$csv_output .= "\n"; 

$values = mysql_query("SELECT * FROM wp_posts 
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id) 
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id) 
INNER JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id) WHERE 1=1 
AND ((post_date >= '2014-11-03 00:00:00' AND post_date <= '2014-12-31 23:59:59')) 
AND wp_posts.post_type = 'videorepot' 
AND (wp_posts.post_status = 'publish') 
AND ((wp_postmeta.meta_key = 'agree' AND CAST(wp_postmeta.meta_value AS CHAR) = '1') 
AND (mt1.meta_key = 'opt-in' AND CAST(mt1.meta_value AS CHAR) = '1') 
AND (mt2.meta_key = 'status' AND CAST(mt2.meta_value AS CHAR) = 'Video Ready')) 
GROUP BY wp_posts.ID 
ORDER BY wp_posts.post_date DESC 
LIMIT 0,9999"); 
while ($rowr = mysql_fetch_row($values)) { 

     $postID = $rowr[0];   
     $user_email = get_post_meta($postID, 'email_address', true); 
     $photo1 = get_post_meta($postID, 'photo_1', true); 
     $photo2 = get_post_meta($postID, 'photo_2', true); 
     $photo3 = get_post_meta($postID, 'photo_3', true); 
     $videourl = get_post_meta($postID, 'the_video', true); 

     // $csv_output .= $rowr['']."; "; 
     $csv_output .= $user_email.', '.$photo1.', '.$photo2.', '.$photo3.', '.$videourl.','; 
     $csv_output .= "\n"; 

} 

$output_filename = "export_".date("Y-m-d_H-i",time()).".csv"; 
header("Content-type: application/vnd.ms-excel"); 
header("Content-disposition: csv" . date("Y-m-d_H-i",time()) . ".csv"); 
header("Content-disposition: filename=".$output_filename); 
print_r($csv_output); 
exit; 

我希望这可以帮助处理内存问题的其他人。

0

我也越来越“试图分配更多的内存致命错误”,但我的解决方案是内部while循环,我错过这一行:

$wp_query->the_post(); 

可能是有益的,如果别人也面临着同样的问题。