Кастомный экспорт заказов MiniShop2

Всем привет! Давно хотел поделиться данным кейсом, который «валяется на полке».

Спросите, а зачем? Есть же готовые компоненты… Ну, вы же знаете, я не сторонник платных решений, да и зачем покупать «самолёт», когда нужна «телега».

Накидал несколько сниппетов, которыми можно вывести все заказы сайта…



Сразу напишу, решение сырое, требует доработки, но уже сейчас может помочь страждущим сделать экспорт и при этом, если руки позволяют, доработать его индивидуально под проект как надо.

Сниппет getOrders получает все заказы сайта:
<?php
$tpl = $modx->getOption('tpl',$scriptProperties,'tpl.Order');

$q = $modx->newQuery('msOrder');
$results = $modx-> getIterator('msOrder', $q);

foreach ($results as $result) {
    $resultArray = $result->toArray();
    $output .= $modx->getChunk($tpl,$resultArray)."\n";
}
$output= "ID заказа;Номер заказа;Статус;Способ доставки;Способ оплаты;Дата заказа;Стоимость заказа;Товары;Получатель;Телефон;Комментарий\n".$output;

$user_agent = getenv("HTTP_USER_AGENT");
if(strpos($user_agent, "Win") !== FALSE) {
    $output = iconv("UTF-8", "CP1251", $output);
} elseif(strpos($user_agent, "Mac") !== FALSE) {
    $output = iconv("UTF-8", "macCyrillic", $output);
}

return $output;

Чанк tpl.Order:
[[+id]];[[+num]];[[+status:is=`1`:then=`Новый`]][[+status:is=`2`:then=`Оплачен`]][[+status:is=`3`:then=`Отправлен`]][[+status:is=`4`:then=`Отменён`]];[[+delivery:is=`1`:then=`Самовывоз`]][[+delivery:is=`2`:then=`Купить в 1 клик`]];[[+payment:is=`1`:then=`Оплата наличными`]];[[+createdon:strtotime:RusDate=`%j %month %Yг. в %H:%m`]];[[+cost]];[[!msOrdersProducts?order=`[[+id]]`&tpl=`tpl.order_products_row`]];[[!getOrderAddress?userid=`[[+user_id]]`&tpl=`tpl.OrderAddress`]]

Сниппет msOrdersProducts — получает товары заказа:
<?php
// выводит товары заказа.
$tpl = $modx->getOption('tpl',$scriptProperties,'tpl.order_products_row'); // если товар найден
$tpl_empty = $modx->getOption('tpl',$scriptProperties,'tpl.order_row_empty'); // если товар не найден

// ищем товар по id заказа
$q = $modx->prepare("SELECT * FROM ".$modx->getOption('table_prefix')."ms2_order_products WHERE order_id=".$order);
$q->execute();
$results = $q->fetchAll(PDO::FETCH_ASSOC);

$output;
// перебором либо выводим нужный заказ, либо оповещаем что его уже нет
foreach ($results as $result) {
  $res = $modx->getObject('modResource', array('pagetitle'=>$result['name']));
  
  if ($res) {
    $resArray = $res->toArray();
    $output .= $modx->getChunk($tpl,$resArray);
  } else {
    $prodName = $modx->setPlaceholder('name', $result['name']);
    $output .= $modx->getChunk($tpl_empty);
  }
}
return $output;

Чанк tpl.order_products_row:
[[+pagetitle]] |

Сниппет getOrderAddress — получает данные о покупателе:
<?php
$userID = $modx->getOption('userid', $scriptProperties);
$tpl = $modx->getOption('tpl', $scriptProperties, 'tpl.OrderAddress');
$output = '';

$q = $modx->prepare("SELECT * FROM ".$modx->getOption('table_prefix')."ms2_order_addresses WHERE user_id=".$userID);
$q->execute();
$results = $q->fetchAll(PDO::FETCH_ASSOC);

foreach ($results as $result) {
    $output = $modx->getChunk($tpl, $result);
}

return $output;

Чанк tpl.OrderAddress:
[[+receiver]];[[+phone]];[[+comment:strip]]

Данная статья, по большей части является пока что заметкой, где время от времени я буду дополнять информацию и дорабатывать код. Ну а пока что, это хоть какое то решение, которое позволит достичь поставленных задач от заказчиков по вопросу выгрузки заказов…

P.S. Что бы скачивался CSV файл, создаём новый тип содержимого с таким форматом, создаём ресурс без шаблона и с этим типом содержимого, ну и вызываем getOrders в content

P.P.S. Если на выводе получаете пустой файл, значит в заказах есть смайлы и ваша БД не utf8mb4, лучше поправить…
Денис Усманов
10 октября 2023, 01:57
modx.pro
3
738
+5

Комментарии: 1

Николай Савин
10 октября 2023, 07:39
1
+4
Позволю себе несколько замечаний.

1. Если заказов много — такой сниппет не сможет выполнить свою работу. Лучше вешать задачу на планировщик

2. Использование getCollection. Это не лучший вариант. Этот метод загружает в ОЗУ сразу всю коллекцию объектов заказа, что не лучшим образом отражается на производительности и ресурсах. Лучше использовать итератор через метод getIterator. Такой метод загружает в память только список объектов, при переборе по очереди достает из базы информацию. Этот метод существенно быстрее работает и кушает меньше ресурсов. К слову итератор это не изобретение MODX. Это паттерн PHP. Да и не только PHP — он почти во всех языках используется.

3. Это что за странная конструкция такая?
$modx->getOption('table_prefix')."ms2_order_addresses
Зачем так? Почему? Есть же гораздо более корректный метод обращения к таблице
$modx->getTableName('msOrderAddress');
Так-то люди вполне могут переименовать таблицу, просто указав нужное имя в модельке. И приведенный метод гарантировано выдаст нужную таблицу.

4. Использовать getChunk я бы рекомендовал так:

$pdoTools = $modx->getService('pdoTools');
$pdoTools->getChunk('name', $params);
Этот вариант, в отличие от $modx->getChunk обработает конструкции и MODX и феном.

5. Не ошибка. Даже не предупреждение. Скорее глаз режет.
Использование прямых SQL конструкций.

Мы же в MODX работаем. Желательно использовать конструктор запроса. newQuery — его не просто так придумали. Помимо универсальности запроса, не привязанного к конкретной СУБД — это еще и выглядит красиво, аккуратно, профессионально. Сразу видно, что человек знает свое рабочее место.
    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
    1