Я сделал этот скрипт, в котором я запускаю WP_Query(), который получает около 2000 записей и продолжает расти. Я хочу иметь возможность записывать эти результаты в файл CSV. У меня это работает, когда для posts_per_page установлено значение 300 или меньше записей.
Если я изменю 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. Есть ли способ указать эти мета_ключи, чтобы при экспорте таблицы я мог просто получить 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
Я опубликовал решение своего ответа. Спасибо за помощь Дэвид.