Подготавливаем ЛК для "ГдеПосылка"
Это продолжение статей по работе с заказами MS2, в последней статье я обещал, что расскажу как интегрировать сервис «ГдеПосылка» в Minishop2, а пока я жду пока очухается администрация «ГдеПосылка» чтобы дать мне доступ к API подготовим почву для интеграции, что мы будем делать:
- Добавим новое поле в заказы minishop2
- Сделаем вывод для пользователей их историю заказов без extJS и каких либо дополнений, на чистом pdoTools
- Научимся делать leftJoin и select на pdoTools и pdoFetch
- Бонусом идут сразу готовые стили для всего этого добра и написанный JS
За объяснением кода — под кат, за кодом на GitHub
Требования к фронту сайта:
- Jquery
- FontAwesome (не обязательно)
- FancyBox 3
А теперь перейдем собственно к разработке:
Первое и самое важное — это добавляем новое поле к заказам MS2. Для этого воспользуемся разделом о плагинах товаров MS2 в официальной доке там написано как расширить свойства товара, но способ работает для любой модели MS2, это нам необходимо для того, чтобы MODX и MS2 увидел и мог работать с кастомными столбцами в БД.
Первым делом нам надо прописать новую карту объекта, для этого создадим index.php и msOrder.inc.php в index.php мы указываем карту какого объекта MS2 мы расширяем, а в msOrder.inc.php мы указываем какие поля добовляем, объяснять не вижу смысла, просто покажу файлы тут, если будут вопросы по ним — задавайте в комментариях
core/components/orderCustomField/index.php
<?php
return array(
'map' => array(
'msOrder' => require_once 'msOrder.inc.php',
),
);
core/components/orderCustomField/msOrder.inc.php<?php
return array(
'fields' => array (
'track' => NULL,
),
'fieldMeta' => array(
'track' => array (
'dbtype' => 'varchar',
'precision' => '100',
'phptype' => 'string',
'null' => true,
),
),
);
Также нам нужно добавить поле track в таблицу modx_ms2_orders, для этого в консоле выполним код:$table = $modx->getTableName('msOrder');
$sql = 'ALTER TABLE ' . $table . ' ADD `track` VARCHAR(255) NULL;';
$modx->exec($sql);
Для того, чтобы minishop2 подхватил наш плагин — нам нужно выполнить код в консоле:if ($miniShop2 = $modx->getService('miniShop2')) {
$miniShop2->addPlugin('orderCustomField', '{core_path}components/orderCustomField/index.php');
}
На данном этапе MS2 уже полностью видит наше поле, вы можете с ним полноценно работать, добавлять его в письма к клиентам или обрабатывать на фронте, везде, где доступны данные заказов, но нам нужно само поле в админку, для этого создадим новый плагин на событие msOnManagerCustomCssJs с вот таким содержимым:<?php
switch ($modx->event->name) {
case 'msOnManagerCustomCssJs':
//проверяем на какой странице мы находимся, если это страница orders, то добавляем наш html
if ($page != 'orders') return;
$modx->controller->addHtml("
<script type='text/javascript'>
Ext.ComponentMgr.onAvailable('minishop2-window-order-update', function(){
this.fields.items[0].items[3].items[0].items.push(
{xtype: 'textfield', name: 'track', fieldLabel: 'Трек - номер', anchor: '100%'}
);
});
</script>");
break;
}
Тут код не вижу смысла объяснять, он прост как три рубля, мы просто добавляем в массив extJS наш объект, скажу лишь только то, что если вы хотите добавить в какое-то другое место, то дебажте расположение элементов вот так: console.log(this.fields)
А там уже по дереву объектов смотрите где находятся нужные вам поля и пуште в нужный массив ваш объект.На этом добавление поля закончилось, перейдем к более интересному — выводу заказов пользователя!
Для вывода заказов мы будем использовать только pdoTools и pdoFetch, подразумевается, что у ваших пользователей уже есть ЛК и страница отведенная под историю заказов
На странице отведенную под историю заказов копируем содержимое файла:
/assets/components/MyCustomOrders/chunk/chunk.tpl.html
html и css я не вижу смысла рассматривать, а вот вызов pdoTools думаю будет многим интересен:
[[!pdoResources?
&class=`msOrder`
&sortby=`createdon`
&leftJoin=`{
"msDelivery":{"class":"msDelivery", "on":"msDelivery.id = msOrder.delivery"},
"msPayment":{"class":"msPayment", "on":"msPayment.id = msOrder.payment"},
"msOrderStatus":{"class":"msOrderStatus", "on":"msOrderStatus.id = msOrder.status"},
"msOrderAddress":{"class":"msOrderAddress", "on":"msOrderAddress.id = msOrder.address"}
}`
&select=`{
"msOrder": "*",
"msDelivery": "msDelivery.name as deliveryName",
"msPayment": "msPayment.name as paymentName",
"msOrderStatus": "msOrderStatus.name as statusName, msOrderStatus.color",
"msOrderAddress": "*"
}`
&where=`{"msOrder.user_id":[[+modx.user.id]]}`
&showLog=`0`
&limit=`9999`
&tpl=`order_row`
]]
И так, что же мы делаем в этом вызове?Первым делом мы обращаемся к модели msOrder и достаем из нее только те записи, которые соответствуют id текущего пользователя, за это отвечает параметр where
&where=`{"msOrder.user_id":[[+modx.user.id]]}`
Далее мы подключаем таблицы msDelivery, msPayment, msOrderStatus и msOrderAddress через leftJoin msDelivery нам нужен для того, чтобы узнать название метода доставки, msPayment для названия метода оплаты, а msOrderStatus нам нужен для названия статуса и для выбранного цвета текущего статуса (все эти пункты в msOrder лежат как id и по id текущего заказа мы достаем массив статуса, доставки и оплаты). В msOrderAddress лежат все поля введенные пользователем на моменте оформления заказа.
Теперь перейдем к select. В селекте мы указываем то, какие поля нам нужны от каждой таблицы, пойдем по порядку:
msOrder — выбираем все поля
msDelivery — нужно только название, его и выбираем и даем ему псевдоним deliveryName
msPayment — аналогично с msDelivery
msOrderStatus — выбираем имя, даем псевдоним и выбираем цвет
msOrderAddress — выбираем все
Чанк order_row лежит тут
Вот в принципе и все, копируем разметку, не забываем подключить JS и стили, единственное что можно рассмотреть отдельно, это то, как в модалке мы получаем данные, для этого у нас в js есть ajax запрос на контроллер, который через pdoFetch запускает выборку с аналогичными параметрами, что и pdoTools ну и еще одну выборку по msProductData, чтобы подтянуть позиции заказа.
Как то слишком сумбурный туториал получился, потому что я не особо понимаю что нужно разжевывать, а что и так очевидно, если возникли вопросы — задавайте в комментариях, главная цель, с которой писалась эта статья, это НАУЧИТЬ НОВИЧИКОВ, по этому непонятные вам вещи можем разобрать в комментариях.
P.s. кто ждет статьи про интеграцию «где посылка» советую сразу оставить заявку на доступ к их API, потому что думают они очень долго и только пару дней назад дали доступ, хотя оставил я заявку 2 недели назад
Поблагодарить автора
Отправить деньги
Комментарии: 46
За стилизацию заказов я брал пример с modstore, я надеюсь никто не обидится, потому что мне кажется что у нового дизайна модстора очень удачное стиливое решение истории заказовБез проблем. Приятно, что нравится!
—
Выкладывай уже свой первый доп к нам ;)
Скоро, если по времени все получится :)
Требования к фронту сайта:Третий бутстрап c jQuery выше 2.2.4 не работает… Мне кажется, что бутстрап — это одна из must have в плане поддержки для компонентов.
Jquery 3+ (на более низких версиях не тестировалось)
На jquery ниже третей я не проверял просто, скорее всего будет работать.
По поводу бутстрапа промолчу, я считаю хенжество тянуть такие вещи как бутстрп, в проект, когда есть flexbox
По поводу бутстрапа промолчу, я считаю хенжество тянуть такие вещи как бутстрп, в проект, когда есть flexbox
github.com/pavel-one/Modx-Custom-Orders-MS2/blob/master/assets/components/MyCustomOrders/js/customOrders.js
Решил код глянуть и в первой же строчке проблема есть…
Решил код глянуть и в первой же строчке проблема есть…
В чем проблема?
jquery.com/upgrade-guide/3.0/#deprecated-document-ready-handlers-other-than-jquery-function
В общем, начиная с 3 версии в jQuery иначе реализовано многое и я сталкивался со случаями, когда не работает:
В общем, начиная с 3 версии в jQuery иначе реализовано многое и я сталкивался со случаями, когда не работает:
$(document).ready(function() {
Если я не ошибаюсь, то все из-за того, что раньше ready был event, а сейчас это Promise. Лично я пишу так:$.when($.ready).then(function(){...});
Да ладно? Даже на 1.12 jquery работает все нормально с реди
Вот пример:
codepen.io/pavel_one/pen/RLdbEG
Проверяйте пожалуйста, прежде чем написать что-то
Вот пример:
codepen.io/pavel_one/pen/RLdbEG
Проверяйте пожалуйста, прежде чем написать что-то
Естественно, что на 1.12 пашет, т.к. ДО 3 был ready, а после уже нет.
Deprecated: document-ready handlers other than jQuery(function)
Due to historical compatibility issues there are a multitude of ways to set a document ready handler. All of the following are equivalent and call the function fn when the document is ready:
$(fn);
$().ready(fn);
$(document).ready(fn);
$(«selector»).ready(fn);
As of jQuery 3.0 the recommended way to add a ready handler is the first method, $(fn). As noted in the Event section, the $(document).on(«ready», fn) event form has slightly different semantics and was removed in jQuery 3.0.
Вот этого не знал, спасибо
Не за что. Очень распространенная ошибка на самом деле. Раньше у document был event на готовность, а теперь Promise. Но как бы оно ни было в данном случае ВООБЩЕ по фигу, т.к. у тебя просто обработку на клик вешает, а для этого вообще дожидаться готовности не нужно да нет никаких причин ждать чего либо вообще, кроме загрузки непосредственного самого jQuery :-)
Короче, тупо убери document и просто click оставь и будет счастье
Короче, тупо убери document и просто click оставь и будет счастье
Все последние работы делаю на Bootstrap 3 + jQuery v3.2.1, если не требуется mSearch2
Я, правда, многое вырезаю, но основной функционал оставляю.
Вот пример, дабы не быть голословным.
mSearch2 с jQuery v3.2.1 — это да, некорректная работа
Я, правда, многое вырезаю, но основной функционал оставляю.
Вот пример, дабы не быть голословным.
mSearch2 с jQuery v3.2.1 — это да, некорректная работа
"msOrderAddress":{"class":"msOrderAddress", "on":"msOrderAddress.id = msOrder.id"}
Ошибка. У них связь:"msOrderAddress":{"class":"msOrderAddress", "on":"msOrderAddress.address= msOrder.id"}
Да ладно? joxi.ru/zANd1x3IBWMJjm
Код скопирован с продакшена и прямо сейчас работает на одном сайте, можете сделать в консоле выборку через pdoFetch и убедиться что вы неправы
Код скопирован с продакшена и прямо сейчас работает на одном сайте, можете сделать в консоле выборку через pdoFetch и убедиться что вы неправы
github.com/bezumkin/miniShop2/blob/e8d674f0ebf80450c3bb3830dfd49413f44a84ff/core/components/minishop2/model/schema/minishop2.mysql.schema.xml#L278
Вот, пожалуйста…
Вот, пожалуйста…
Код скопирован с продакшена и прямо сейчас работает на одном сайтеТы фортовый, что тут еще скажешь :-) Видимо ошибка не всплыла, т.к. во всех заказах по одному товару и поэтому ID в таблицах шли вровень :-)
Еще раз прошу проверять что-то, перед тем как написать, joxi.ru/D2PK71nTp9LjOm
Вот тут вообще не понял, о чем вы? :)
'on' => 'msOrderAddress.id = msOrder.id'
На гите косяк у связи
На гите косяк у связи
В какой строке я то понял, а как должно быть по вашему, вот этого я понять не могу
'on' => 'msOrderAddress.id = msOrder.id'В msOrder поле для связи address!
На гите косяк у связи
'on' => 'msOrderAddress.id = msOrder.address'
для pdoResources"msOrderAddress":{"class":"msOrderAddress", "on":"msOrderAddress.id = msOrder.address"}
А, вот теперь понял, спасибо, да, не заметил этого
И снова не за что :-)
Ну и последнее… Напиши правильно для кого адресована статья :-) Что за Новчики? :-)
Ну и последнее… Напиши правильно для кого адресована статья :-) Что за Новчики? :-)
это НАУЧИТЬ НОВЧИКОВ
github.com/bezumkin/miniShop2/blob/e8d674f0ebf80450c3bb3830dfd49413f44a84ff/core/components/minishop2/model/minishop2/mysql/msorder.map.inc.php#L277
Снова ссылка на github… Обрати внимание чей он ;-)
Снова ссылка на github… Обрати внимание чей он ;-)
как должно быть по вашему, вот этого я понять не могуТак что не только по-моему ;-)
Более того на github у тебя снова:
github.com/pavel-one/Modx-Custom-Orders-MS2/blob/7f37b69d4bcf1515a5dde3e191dd812e8c6aeedb/assets/components/MyCustomOrders/action/getOrder.php#L32
А Еще
github.com/pavel-one/Modx-Custom-Orders-MS2/blob/7f37b69d4bcf1515a5dde3e191dd812e8c6aeedb/assets/components/MyCustomOrders/action/getOrder.php#L43
и
github.com/pavel-one/Modx-Custom-Orders-MS2/blob/7f37b69d4bcf1515a5dde3e191dd812e8c6aeedb/assets/components/MyCustomOrders/action/getOrder.php#L9
Не продуман момент для случаев, когда контекст не web
github.com/pavel-one/Modx-Custom-Orders-MS2/blob/7f37b69d4bcf1515a5dde3e191dd812e8c6aeedb/assets/components/MyCustomOrders/action/getOrder.php#L32
А Еще
github.com/pavel-one/Modx-Custom-Orders-MS2/blob/7f37b69d4bcf1515a5dde3e191dd812e8c6aeedb/assets/components/MyCustomOrders/action/getOrder.php#L43
и
github.com/pavel-one/Modx-Custom-Orders-MS2/blob/7f37b69d4bcf1515a5dde3e191dd812e8c6aeedb/assets/components/MyCustomOrders/action/getOrder.php#L9
Не продуман момент для случаев, когда контекст не web
А ЕщеА тут что не так?
github.com/pavel-one/Modx-Custom-Orders-MS2/blob/7f37b69d4bcf1515a5dde3e191dd812e8c6aeedb/assets/components/MyCustomOrders/action/getOrder.php#L43
и
github.com/pavel-one/Modx-Custom-Orders-MS2/blob/7f37b69d4bcf1515a5dde3e191dd812e8c6aeedb/assets/components/MyCustomOrders/action/getOrder.php#L9
Не продуман момент для случаев, когда контекст не webУж такие вещи для обучающей статьи продумывать не имеет смысла, статья находится в разделе «Пошаговые инструкции», а не в разделе «Готовые решения»
А ЕщеВсе таки еще раз что тут не так? Пока ты не ушел)
github.com/pavel-one/Modx-Custom-Orders-MS2/blob/7f37b69d4bcf1515a5dde3e191dd812e8c6aeedb/assets/components/MyCustomOrders/action/getOrder.php#L43
и
github.com/pavel-one/Modx-Custom-Orders-MS2/blob/7f37b69d4bcf1515a5dde3e191dd812e8c6aeedb/assets/components/MyCustomOrders/action/getOrder.php#L9
Ок. Через минут скину сюда код
Нашел еще ошибку:
в getOrder.php ты вначале:
define('MODX_API_MODE', true);
Далее во-первых нет проверки на пустой id в POST
Ну а во-вторых ты sendRedirect делаешь, если не AJAX.
Что интересно: MODX_API_MODE не даст запустить handleRequest… Не понятен redirect. Нужно сразу exit хотя бы или т.п.
в getOrder.php ты вначале:
define('MODX_API_MODE', true);
Далее во-первых нет проверки на пустой id в POST
Ну а во-вторых ты sendRedirect делаешь, если не AJAX.
Что интересно: MODX_API_MODE не даст запустить handleRequest… Не понятен redirect. Нужно сразу exit хотя бы или т.п.
Редирект отлично срабатывает
ТЫК
ТЫК
Короче, вместо него $modx->sendErrorPage();
Я знаю метод на редирект страницы ошибки, и если бы мне нужно было бы редиректить на страницу ошибки, я бы его использовал %)
Далее во-первых нет проверки на пустой id в POSTА зачем она нужна? Если пользователь не подхватил ID то и запрос у него не пойдет, а если кто-то решит шаловливыми ручками поэксперементировать, то ему во первых не составит труда подставить туда любое значение чтобы обойти проверку, а во вторых ничего страшного не случится если id не придет
ну давай я передам в console не число а массив… Или что там в pdoFetch передается, чтобы преобразовать в более сложный where?
И ничего не произойдет, представляешь?) Однако если бы даже был бы шанс чему то произойти, то проверка на пустоту не оберегла бы от атаки, проверка на число — уберегла бы, но в нашем случае не произойдет ровным счетом ничего даже если массив придет. К слову нельзя передать массив через POST, он просто придет строкой
Теперь нам нужно добавить собственно наше поле «track» в нашу БДЕсли будет писаться компонент в modstore, то вместо этого надо:
Через phpMyAdmin перейдем в таблицу modx_ms2_orders -> структура и добавим поле в самый конец:
Имя: track
Тип: varchar
Длина: 255
Null: true
$manager = $modx->getManager();
и уже им таблицу изменять
Этот компонент писаться в modstore не будет, иначе бы и статей небыло бы
Все сделал по инструкции, в итоге на странице заказов белый лист и в логе
[2018-02-26 08:23:39] (ERROR @ /home/s1111/www/core/components/pdotools/model/pdotools/pdotools.class.php : 977) Unexpected token ':' in c307b02e5743bce69f94649b8a8d7c6d line 78, near '{"class":' <- there
Куда рыть?
переписал так и все заработало:
[[!pdoResources?
&class=`msOrder`
&sortby=`createdon`
&leftJoin=`{
"msDelivery":{
"class":"msDelivery", "on":"msDelivery.id = msOrder.delivery"
},
"msPayment":{
"class":"msPayment", "on":"msPayment.id = msOrder.payment"
},
"msOrderStatus":{
"class":"msOrderStatus", "on":"msOrderStatus.id = msOrder.status"
},
"msOrderAddress":{
"class":"msOrderAddress", "on":"msOrderAddress.id = msOrder.address"
}
}`
&select=`{
"msOrder": "*",
"msDelivery": "msDelivery.name as deliveryName",
"msPayment": "msPayment.name as paymentName",
"msOrderStatus": "msOrderStatus.name as statusName, msOrderStatus.color",
"msOrderAddress": "*"
}`
&where=`{
"msOrder.user_id":[[+modx.user.id]]
}`
&showLog=`0`
&limit=`9999`
&tpl=`order_row`
]]
Заметил, что если в заказе будет больше 10 товаров, то выводятся только 10, остальные не выводятся.
Фиксанул вот таким образом:
joxi.ru/n2Yb80aCZOzkaA
Фиксанул вот таким образом:
joxi.ru/n2Yb80aCZOzkaA
Для этого в pdoResources существует такой параметр как limit, также можно выводить через pdoPage для пагинации
Спасибо! А как можно получить изображения товаров при открытии popup в заказе? В response их нет, как их можно достать?
Вам нужно приджойнить таблицу msProductFile по аналогии с другими
А можете подсказать, как это правильно сделать? Пробую вот так в файле getOrder.php
// get images
'msProductFile' => array(
'class' => 'msProductFile',
'on' => array(
'msProduct.id = msProductFile.product_id',
'msProductFile.parent' => 0,
'msProductFile.type' => 'image',
)
)
),
'select' => array(
'msOrder' => '*',
'msDelivery' => 'msDelivery.name as deliveryName',
'msOrderStatus' => 'msOrderStatus.name as statusName',
'msPayment' => 'msPayment.name as paymentName',
'msOrderAddress' => '*',
//
'msProductFile' => 'all'
),
Ребята, что делать если в {$track} в уведомлении о движении посылки на работает, на почту он приходит как есть — {$track}.
Еще вопрос, можно ли как то вывести поле с треком на страницу заказа?
Еще вопрос, можно ли как то вывести поле с треком на страницу заказа?
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.