WordPress — Ограничение памяти PHP на создание CSV из БД — Как уменьшить объем памяти, который использует PHP?

Я запускаю запрос БД здесь, и использую mysqli с MYSQLI_USE_RESULT чтобы выполнить запрос быстрее. Но здесь требуется php-манипулирование данными, поэтому это не так просто, как просто запись в CSV-файл в каждой возвращаемой строке. Я знаю, что запрос к базе данных заканчивается (хотя он и занимает много времени), но запрос базы данных завершается, поэтому проблема должна быть в стороне памяти PHP, потому что я получаю 504 Gateway Timeout Error. Мой код для этого выглядит следующим образом:

global $wpdb, $root_dir;

if (!defined('ABSPATH'))
$root_dir = dirname(__FILE__) . '/';
else
$root_dir = ABSPATH;

require_once($root_dir . 'wp-config.php');
$wp->init();
$wp->parse_request();
$wp->query_posts();
$wp->register_globals();

$start_date = !empty($_GET['start']) ? DateTime::createFromFormat('Y-m-d', $_GET['start']) : '';
$end_date = !empty($_GET['end']) ? DateTime::createFromFormat('Y-m-d', $_GET['end']) : '';

$append = array();

if (!empty($start_date))
$append[] = $start_date->format('Y-m-d');

if (!empty($end_date))
$append[] = $end_date->format('Y-m-d');

$filename = 'user-export' . (!empty($append) ? '_' . implode('_', $append) : '');

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=\"" . $filename . ".csv\"");
header("Expires: 0");
header("Pragma: public");


ini_set('memory_limit', '-1');
ini_set('max_execution_time', '-1');
set_time_limit(0);

$headers = array('Order Date/Time', 'Name', 'Billing Address', 'Shipping Address', 'Phone', 'Email Address');
$meta_keys = array('_billing_first_name', '_billing_last_name', '_billing_address_1', '_billing_address_2', '_billing_city', '_billing_state', '_billing_postcode', '_billing_email', '_billing_country', '_billing_phone', '_shipping_address_1', '_shipping_address_2', '_shipping_city', '_shipping_state', '_shipping_postcode', '_shipping_country');
$csv_data = $emails = $order_ids_skipped = $meta = array();

// Using an unbuffered query...
$mysqli  = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);

if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}

$uresult = $mysqli->query("SELECT p.ID, p.post_date, pm.meta_key, pm.meta_value
FROM {$wpdb->posts} AS p
INNER JOIN {$wpdb->postmeta} AS pm ON (pm.post_id = p.ID AND pm.meta_key IN ('" . implode("','", $meta_keys) . "'))
WHERE p.post_type = 'shop_order' AND p.post_status IN ('wc-sent-delivery', 'wc-awaiting-delivery', 'wc-completed')" . (!empty($start_date) && !empty($end_date) ? " AND (p.post_date >= '" . $start_date->format('Y-m-d') . " 00:00:00' AND p.post_date <= '" . $end_date->format('Y-m-d') . " 23:59:59')" : "") . "ORDER BY p.post_date DESC", MYSQLI_USE_RESULT);

if ($uresult)
{
while ($order_query = $uresult->fetch_assoc())
{
// If the email already exists, continue...
if ($order_query['meta_key'] == '_billing_email' && !empty($emails) && in_array($order_query['meta_value'], $emails))
{
if (isset($csv_data[$order_query['ID']]))
unset($csv_data[$order_query['ID']]);

if (isset($meta[$order_query['ID']]))
unset($meta[$order_query['ID']]);

$order_ids_skipped[] = $order_query['ID'];

continue;
}

if (in_array($order_query['ID'], $order_ids_skipped)) continue;

if (!isset($csv_data[$order_query['ID']]))
$csv_data[$order_query['ID']] = array(
'order_date' => $order_query['post_date']
);

$meta[$order_query['ID']][$order_query['meta_key']] = $order_query['meta_value'];

if ($order_query['meta_key'] == '_billing_email')
$emails[] = $order_query['meta_value'];
}
}
$uresult->close();

if (!empty($meta))
{
foreach($meta as $order_id => $meta_data)
{
$billing = array(
'addr1' => !empty($meta_data['_billing_address_1']) ? $meta_data['_billing_address_1'] : '',
'addr2' => !empty($meta_data['_billing_address_2']) ? $meta_data['_billing_address_2'] : '',
'city' => !empty($meta_data['_billing_city']) ? $meta_data['_billing_city'] : '',
'state' => !empty($meta_data['_billing_state']) ? $meta_data['_billing_state'] : '',
'zip' => !empty($meta_data['_billing_postcode']) ? $meta_data['_billing_postcode'] : '',
'country' => !empty($meta_data['_billing_country']) ? $meta_data['_billing_country'] : ''
);
$shipping = array(
'addr1' => !empty($meta_data['_shipping_address_1']) ? $meta_data['_shipping_address_1'] : '',
'addr2' => !empty($meta_data['_shipping_address_2']) ? $meta_data['_shipping_address_2'] : '',
'city' => !empty($meta_data['_shipping_city']) ? $meta_data['_shipping_city'] : '',
'state' => !empty($meta_data['_shipping_state']) ? $meta_data['_shipping_state'] : '',
'zip' => !empty($meta_data['_shipping_postcode']) ? $meta_data['_shipping_postcode'] : '',
'country' => !empty($meta_data['_shipping_country']) ? $meta_data['_shipping_country'] : ''
);

$csv_data[$order_id]['name'] = !empty($meta_data['_billing_last_name']) ? trim($meta_data['_billing_first_name']) . ' ' . trim($meta_data['_billing_last_name']) : trim($meta_data['_billing_first_name']);
$csv_data[$order_id]['billing'] = implode(', ', array_filter($billing));
$csv_data[$order_id]['shipping'] = implode(', ', array_filter($shipping));
$csv_data[$order_id]['phone'] = !empty($meta_data['_billing_phone']) ? $meta_data['_billing_phone'] : '';
$csv_data[$order_id]['email'] = !empty($meta_data['_billing_email']) ? $meta_data['_billing_email'] : '';
}


if (!empty($csv_data))
build_csv_file($csv_data, $headers);
}

// No need to continue here.
exit;

function str_putcsv($input, $delimiter = ',', $enclosure = '"')
{
// $fp = fopen('php://temp', 'r+b');
$fp = fopen('php://output', 'r+b');
fputcsv($fp, $input, $delimiter, $enclosure);
rewind($fp);
rtrim(stream_get_contents($fp), "\n");
fclose($fp);
// return $data;
}

function build_csv_file($data, $headers)
{
global $root_dir;

$output = '';

if (empty($data))
return array();

if (!empty($headers))
str_putcsv($headers, ',', '"') . PHP_EOL;

foreach($data as $part)
str_putcsv($part, ',', '"') . PHP_EOL;
}

Сохраните этот файл как testing.php и выполните следующий URL-адрес из корня WordPress:

https://example.com/testing.php?start=2010-03-05&конец = 2018-03-05

Просто возвращает ошибку 504 шлюза. Это определенно проблема ограничения памяти PHP, однако я подумал, что CSV-файл можно передавать и даже использовать php://output Вот. Не уверен, как лучше справиться с этим, чтобы уменьшить объем используемой памяти PHP, или есть ли способ сделать это правильно, сохраняя при этом правильные данные.

Кто-нибудь может мне помочь? Очень ценится. Я использую версию PHP 7.2, я верю. Можно подумать, что php сможет лучше обрабатывать память в наши дни. Я считаю, что моя память PHP максимально 1024 МБ. Кажется, я все время превышаю ограничение памяти PHP. Становится настоящей неприятностью.

1

Решение

где вы объявляете переменную $ meta

if (isset($meta[$order_query['ID']]))

Кроме того, было бы целесообразно выполнить отладку, поставив exit в каждом блоке операторов, чтобы узнать, какой блок кодов занимает столько памяти, и вы можете оптимизировать только эту часть.

0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector