Php 如何将wp_查询优化为csv脚本?
我制作了这个脚本,运行一个WP_查询,可能会得到2000条记录,并且不断增长。我希望能够将这些结果写入CSV文件。当每页的posts\u设置为300条或更少记录时,我就可以工作了 如果我将posts\u per\u page更改为-1,则会出现以下错误:Php 如何将wp_查询优化为csv脚本?,php,wordpress,csv,memory-management,fputcsv,Php,Wordpress,Csv,Memory Management,Fputcsv,我制作了这个脚本,运行一个WP_查询,可能会得到2000条记录,并且不断增长。我希望能够将这些结果写入CSV文件。当每页的posts\u设置为300条或更少记录时,我就可以工作了 如果我将posts\u per\u page更改为-1,则会出现以下错误: Fatal error: Allowed memory size of 134217728 bytes exhausted 我想知道是否有一种方法可以一次将300条记录发送到CSV文件,直到没有更多记录,然后触发文件下载 或者将每一行流式传输
Fatal error: Allowed memory size of 134217728 bytes exhausted
我想知道是否有一种方法可以一次将300条记录发送到CSV文件,直到没有更多记录,然后触发文件下载
或者将每一行流式传输到CSV文件?在执行FOPSV时,管理内存的最佳方法是什么
以下是我现在拥有的:
$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_查询时仍然遇到内存问题。所以,我写了我的mySQL查询——你知道我是从其他例子中拼凑出来的。这个查询运行得非常快,所以我想我会有更好的运气
我有一个新问题,因为这与meta_键/meta_值有关。目前,我在查询中使用SELECT*,但我不想选择所有内容。我只需要数据库中的大约5个字段。我想要的几个字段是meta_key/meta_value。有没有一种方法可以指定那些meta_键,这样当我导出表时,我就可以得到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,但我已经将限制设置为09999进行了测试,它在phpmyadmin中运行得非常快。当我没有设置限制时,上面的查询提供了大约1282个结果
更新3
我已经发布了我的答案的解决方案。谢谢你的帮助,大卫。我想我已经找到了一个很好的解决办法。这对我来说是可行的,我不需要增加php内存或类似的东西 这是最后一个未经编辑的脚本。请记住,我使用的mysql查询使用一个日期范围和3个meta_键从数据库中获取数据子集。我得到大约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;
我希望这能帮助处理内存问题的其他人。我也尝试分配更多内存致命错误,但我的解决方案是,在while循环中,我错过了这一行:
$wp_query->the_post();
如果其他人也面临同样的问题,可能会有所帮助。增加php内存…或者添加post meta表示您已下载,并将最大结果设置为200左右(不包括下载量)。我不希望简单地增加php内存。在这种情况下,我有兴趣学习适当的PHP技术来管理内存。不过我暂时试试这个。另外,根据错误我允许134 MB的内存,我认为这是相当高的。问题是我想在每次单击链接时导出完整的数据库,因此不需要将项目设置为正在下载。尽管如此,还是感谢您的评论。虽然如此,但您没有134 mb的内存可供使用…但是在循环后取消设置wp查询,并使用while而不是foreach foreach再次创建另一个副本,因此您实际上有3个副本在运行中,然后在循环时取消设置$list数组。确定。我在循环之后添加了wp_reset_查询来重置wp_查询。我对使用while而不是foreach有点困惑,因为我正在将查询结果加载到数组中,然后使用foreach将每个项目添加到CSV中。我可以尝试删除foreach并将fputcsv移动到While循环中。也许这就是你的意思?我确信某处可能有一个未设置的$list函数,我将查找它。Thank.foreach创建数据的一个副本,而在没有副本的情况下沿着数据循环。实际上,您可以使用wp while循环,这样可以节省两次以上的循环。希望您不需要在每次迭代时取消设置值,只需在循环结束时重置post数据即可。