Php 如何将wp_查询优化为csv脚本?

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文件,直到没有更多记录,然后触发文件下载 或者将每一行流式传输

我制作了这个脚本,运行一个WP_查询,可能会得到2000条记录,并且不断增长。我希望能够将这些结果写入CSV文件。当每页的posts\u设置为300条或更少记录时,我就可以工作了

如果我将posts\u per\u page更改为-1,则会出现以下错误:

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数据即可。