MiniShop3 - новый релиз. 1.0.0-alpha.2
Всем привет. MiniShop3 стремительно близится к боевому релизу (очень надеюсь сделать это в ближайшие 2 месяца). А пока спешу поделиться отчетом о проделанной за 1.5 месяца работе и представить для желающих потестировать промежуточный релиз 1.0.0-alpha.2
Объем работы получился самым большим. Решены практически все задачи, которые я ставил перед собой в начале разработки два года назад.
Итак, Давайте посмотрим что же завезли нового.
Я принял решение отказаться от использования классического для MODX phpThumb и использовать в работе лидера среди обработчиков изображений Intervention Image v3
Среди преимуществ хочу отметить
Теперь используем Uppy вместо Plupload
Современная система роутинга API (FastRoute)
В MiniShop3 все запросы улетают в самые настоящие роуты
Роуты для админки обязательно проверяют авторизацию и права доступа. Роуты для фронта работают с пользовательскими токенами, CORS запросами, а также контролируют rate_limit
В обоих случаях предусмотрена возможность создать пользовательский файл внутри core/config/, который дополнит или переопределит системные роуты из коробки.
Service Layer — масштабный рефакторинг
— 15+ сервисов: CategoryService, ProductService, OrderService, OptionService, PaymentService, DeliveryService…
— xPDO модели стали «тонкими» — только ORM
— Бизнес-логика вынесена в сервисы с DI контейнером ($modx->services)
— Lazy loading и singleton pattern
Здесь из важного, в первую очередь, хочу написать, что вся логика MiniShop3 (по большей части) разнесена по сервисам. В miniShop2 сервисами были Корзина, Заказ, Доставка, Оплата. Была возможность переопределять их. Мы их называли handler или контроллеры, но по сути своей это были сервисы.
Сейчас я постарался выстроить архитектуру, когда вся логика проекта разбита на логические части внутри сервисов. Каждый сервис можно переопределить (Работает паттерн Dependency Injection)
К примеру вас не устраивает как работают изображения. Вы хотите подключить другой обработчик, или вынести все в онлайн-сервис, работая с микросервисами. Нет проблем. Просто переопределите ImageService.
Предусмотрен отдельный файл в core/config/ где вы можете указать путь к своему обработчику, перехватывая всю логику. Все просто.
Создаем файл /core/config/ms3.services.php
В него кладем массив
ПОЛНЫЙ СПИСОК ДОСТУПНЫХ СЕРВИСОВ
Обратите внимание. Больше не нужно производить манипуляции с системными настройками.
Если вы создали свой класс Заказа — просто пропишите путь к нему. Вся логика в файлах. Это несомненный плюс с точки зрения версионирования и контроля кода.
Продолжаю модернизацию админки. В прошлой серии я рассказывал о том, как реализовал конструктор полей товара и сменил внешний вид вкладки «Свойства товаров».
Также в начале статьи уже упомянул, что изменил загрузчик изображений. Теперь вкладка Галерея также работает н VUE
Теперь поговорим о новинке. Конструктор гридов. Грид это таблица с записями в extJS. Кто помнит как мы могли управлять таблицами? К примеру как мы добавляли поля в таблицу товаров, или таблицу заказов? Для каждой из важных таблиц была системная настройка, где через запятую можно было перечислить поля. На этом и все.
Я реализовал настоящий визуальный конструктор
1. Выбираете таблицу
2. Кнопками настраиваете нужные вам поля в любом удобном порядке
3. Сразу же указываете по каким колонкам будете фильтровать и сортировать.

на выходе получаем такую таблицу (на данный момент нет пользователей, заменю потом изображение на заполненную таблицу)

Из интересного. Поля в конфигураторе можно задать несколькими способами
1. Модельные поля. Выбираем колонки, которые есть в таблице-модели
2. Шаблонные поля. Задаем сочетание модельных полей {last_name} {first_name}
3. Присоединямые поля. Выполняем Join из других таблиц. В том числе с использованием агрегатных функций COUNT, SUM и так далее К примеру можем в таблице Клиенты можем быстро вывести колонку Кол-во покупок, присоединив таблицу заказов и посчитав количество записей по конкретному клиенту. Вычисления оптимизированы. Не получится такого. что на каждую из записей мы делаем дополнительный запрос.
4. Вычисляемые поля. Тут можно реализовать любую PHP логику. Посчитать средний чек каждого клиента, например. Здесь указываем путь к файлу, который что-то посчитает и вернет ответ. По сути сниппет, только файловый. Желательно не использовать запросы к базе, потому что логика будет исполняться для каждой записи таблицы.
5. Поля-действия. Здесь настраиваем кнопки действий. Здесь предусмотрена отдельная логика с подключением JS скриптов. Подробнее будет в документации.
Модель msCustomer — полноценная сущность
— Отдельная от modUser система клиентов
— Токены авторизации (API, refresh, magic links)
— Адреса доставки с полем is_default
— GDPR поля (consent, marketing)
Личный кабинет клиента (Frontend)
— Страница адресов (/cabinet/addresses)
— Установка адреса по умолчанию
— Удаление с подтверждением
— Страница заказов (/cabinet/orders)
— Фильтрация по статусу
— Пагинация
— Детальный просмотр заказа
— Web API для управления адресами
Система авторизации клиентов
— RegisterService с автологином после регистрации
— AuthManager для входа/выхода
— TokenMiddleware с поддержкой сессии и API токенов
— RateLimiter для защиты от брутфорса
Полноценное управление клиентами из админки
Из интересного, постарался реализовать подключаемые сервисы авторизации. По умолчанию авторизация через email + пароль. Но можно подключить например SMS, или комбинировать способы. Подробнее будет описано в документации
Были и неудачные работы, которые после проработки и долгого обсуждения пришлось выбросить. Не удалось полностью убрать логику из XPDO файлов.
В идеальной картине программирования Модели должны делать запросы в базу и на этом все. Модель никогда не знает о вышестоящих контроллерах, сервисах, репозиториях.
Вся логика обычно лежит в сервисе или репозитории. Они по мере необходимости дергают модели для операцией с базой данных.
В MODX3 совсем другая логика. Она строится вокруг моделей. Внутри много бизнес-логики. И, к сожалению, эта архитектура наследуюется в самых крупных классах Минишоп msProduct и msCategory. MODX дергает эти xpdo модели напрямую. Нет возможности нормально переопределить поведение. Все что удалось сделать это вынести бизнес-логику в подключаемые сервисы. Но модель все равно подключает сервис, знает о нем и как бы им распоряжается, находясь выше по статусу.
Для всех страниц подготовил обновленные примеры шаблонов и чанков в более-менее современном визуале.
По сути следующая итерация правок — заключительная перед выходом в Beta версию и выкладкой в modstore
Вот что я запланировал сделать:
1. Работа с заказом в админке. Перевожу страницу заказов на VUE. Делаю таблицу и окно заказа конфигурируемым. Планирую переделать логгирование заказа. Оптимизация PHP.
2. Хотелось бы и другие странички доработать, перевести их на VUE. Например Настройки производителей, статусы и так далее. Это не слишком критично, может и позже сделаю.
3. Еще немного поработаю с чанками и шаблонами. Пока не до конца доволен. Нужны доработки.
4. Тесты мультиязычности и мульти-контекстов.
5. Самое важное — документация.
По ощущениям — думаю мне понадобится около двух месяцев на. Возможно получится сделать сообществу подарок к новому году. Тут многое зависит от загруженности на работе.
Далее приступаю к работе над обновлением mSearch. Также запланирована вообще вся линейка жизненно важных компонентов для построения большого интернет-магазина.
Объем работы получился самым большим. Решены практически все задачи, которые я ставил перед собой в начале разработки два года назад.
Итак, Давайте посмотрим что же завезли нового.
Работа с изображениями
Я принял решение отказаться от использования классического для MODX phpThumb и использовать в работе лидера среди обработчиков изображений Intervention Image v3
Среди преимуществ хочу отметить
- Скорость генерации в 3-5 раз выше
- Потребление памяти до 40% ниже
- Поддержка всех современных форматов из коробки, включая Gif, Avif, WebP
- Работа на PHP 8.1+
- Автоматический выбор драйвера: Imagick (приоритет) или GD
- Новые опции для формирования эскизов (blur, brightness, contrast, gamma, greyscale, pixelate, mode (cover, contain) )
Теперь используем Uppy вместо Plupload
- Современный визуальный загрузчик файлов на Vue 3
- Drag & Drop интерфейс с превью изображений
- Встроенный редактор изображений (обрезка, поворот)
- Прогресс загрузки для каждого файла
- Русская локализация
- Поддержка множественной загрузки
- Автоочистка после успешной загрузки
Архитектура и Backend
Современная система роутинга API (FastRoute)
- RESTful API с поддержкой всех HTTP методов
- Middleware система (Auth, Permission, Token)
- Файловая конфигурация роутов (config/routes/*.php)
- Поддержка пользовательских роутов и возможность переопределять системные
switch ($action) {
case 'cart/add':
$response = $this->cart->add(@$data['id'], @$data['count'], @$data['options']);
break;
case 'cart/change':
$response = $this->cart->change(@$data['key'], @$data['count']);
break;
case 'cart/remove':
$response = $this->cart->remove(@$data['key']);
break;
case 'cart/clean':
$response = $this->cart->clean();
break;
case 'cart/get':
$response = $this->cart->get();
break;
case 'order/add':
$response = $this->order->add(@$data['key'], @$data['value']);
break;
case 'order/submit':
$response = $this->order->submit($data);
break;
case 'order/getcost':
$response = $this->order->getCost();
break;
case 'order/getrequired':
$response = $this->order->getDeliveryRequiresFields(@$data['id']);
break;
case 'order/clean':
$response = $this->order->clean();
break;
case 'order/get':
$response = $this->order->get();
break;
default:
$message = ($data['ms2_action'] != $action)
? 'ms2_err_register_globals'
: 'ms2_err_unknown';
$response = $this->error($message);
}По сути был белый список с разрешенными действиями, без прямой возможности этот список расширить, переопределить. В MiniShop3 все запросы улетают в самые настоящие роуты
$router->group('/cart', function($router) use ($modx) {
// POST /api/v1/cart/add - Добавить товар в корзину
$router->post('/add', function($params) use ($modx) {
$controller = new \MiniShop3\Controllers\Api\Web\CartController($modx);
return $controller->add($params);
});
// POST /api/v1/cart/remove - Удалить товар из корзины
$router->post('/remove', function($params) use ($modx) {
$controller = new \MiniShop3\Controllers\Api\Web\CartController($modx);
return $controller->remove($params);
});
// POST /api/v1/cart/change - Изменить количество товара
$router->post('/change', function($params) use ($modx) {
$controller = new \MiniShop3\Controllers\Api\Web\CartController($modx);
return $controller->change($params);
});
// GET /api/v1/cart/get - Получить содержимое корзины
$router->get('/get', function($params) use ($modx) {
$controller = new \MiniShop3\Controllers\Api\Web\CartController($modx);
return $controller->get($params);
});
// POST /api/v1/cart/clean - Очистить корзину
$router->post('/clean', function($params) use ($modx) {
$controller = new \MiniShop3\Controllers\Api\Web\CartController($modx);
return $controller->clean($params);
});
}, [$tokenMiddleware]);Предусмотрено два файла с роутами. web.php для фронта и manager.php для админки. Роуты для админки обязательно проверяют авторизацию и права доступа. Роуты для фронта работают с пользовательскими токенами, CORS запросами, а также контролируют rate_limit
В обоих случаях предусмотрена возможность создать пользовательский файл внутри core/config/, который дополнит или переопределит системные роуты из коробки.
Service Layer — масштабный рефакторинг
— 15+ сервисов: CategoryService, ProductService, OrderService, OptionService, PaymentService, DeliveryService…
— xPDO модели стали «тонкими» — только ORM
— Бизнес-логика вынесена в сервисы с DI контейнером ($modx->services)
— Lazy loading и singleton pattern
Здесь из важного, в первую очередь, хочу написать, что вся логика MiniShop3 (по большей части) разнесена по сервисам. В miniShop2 сервисами были Корзина, Заказ, Доставка, Оплата. Была возможность переопределять их. Мы их называли handler или контроллеры, но по сути своей это были сервисы.
Сейчас я постарался выстроить архитектуру, когда вся логика проекта разбита на логические части внутри сервисов. Каждый сервис можно переопределить (Работает паттерн Dependency Injection)
К примеру вас не устраивает как работают изображения. Вы хотите подключить другой обработчик, или вынести все в онлайн-сервис, работая с микросервисами. Нет проблем. Просто переопределите ImageService.
Предусмотрен отдельный файл в core/config/ где вы можете указать путь к своему обработчику, перехватывая всю логику. Все просто.
Создаем файл /core/config/ms3.services.php
В него кладем массив
return [
'ms3_product_image' => [
'class' => \MyProject\Services\CustomProductImageService::class,
],
];ПОЛНЫЙ СПИСОК ДОСТУПНЫХ СЕРВИСОВ
======================================================================
/*
* Конфигурация:
* -------------
* 'ms3_config_manager' - Менеджер конфигураций
* 'ms3_field_config_manager' - Менеджер конфигураций полей
* 'ms3_config_service' - Фасад над конфиг-менеджерами
*
* Товары:
* -------
* 'ms3_product_data_service' - Работа с данными товаров
* 'ms3_product_image' - Обработка изображений товаров
*
* Поставщики:
* -----------
* 'ms3_vendor_service' - Работа с производителями
*
* Доставка и оплата:
* ------------------
* 'ms3_delivery_service' - Сервис доставки
* 'ms3_payment_service' - Сервис оплаты
*
* Заказы:
* -------
* 'ms3_order_service' - Работа с заказами
*
* Категории:
* ----------
* 'ms3_category_service' - Работа с категориями
* 'ms3_category_option_service' - Опции категорий
*
* Опции товаров:
* --------------
* 'ms3_option_service' - EAV система опций
*
* Утилиты:
* --------
* 'ms3_token_service' - Работа с токенами
* 'ms3_image' - Обработка изображений (Intervention Image)
*/Обратите внимание. Больше не нужно производить манипуляции с системными настройками.
Если вы создали свой класс Заказа — просто пропишите путь к нему. Вся логика в файлах. Это несомненный плюс с точки зрения версионирования и контроля кода.
Админка (ExtJS + Vue)
Продолжаю модернизацию админки. В прошлой серии я рассказывал о том, как реализовал конструктор полей товара и сменил внешний вид вкладки «Свойства товаров».
Также в начале статьи уже упомянул, что изменил загрузчик изображений. Теперь вкладка Галерея также работает н VUE
Теперь поговорим о новинке. Конструктор гридов. Грид это таблица с записями в extJS. Кто помнит как мы могли управлять таблицами? К примеру как мы добавляли поля в таблицу товаров, или таблицу заказов? Для каждой из важных таблиц была системная настройка, где через запятую можно было перечислить поля. На этом и все.
Я реализовал настоящий визуальный конструктор
1. Выбираете таблицу
2. Кнопками настраиваете нужные вам поля в любом удобном порядке
3. Сразу же указываете по каким колонкам будете фильтровать и сортировать.

на выходе получаем такую таблицу (на данный момент нет пользователей, заменю потом изображение на заполненную таблицу)

Из интересного. Поля в конфигураторе можно задать несколькими способами
1. Модельные поля. Выбираем колонки, которые есть в таблице-модели
2. Шаблонные поля. Задаем сочетание модельных полей {last_name} {first_name}
3. Присоединямые поля. Выполняем Join из других таблиц. В том числе с использованием агрегатных функций COUNT, SUM и так далее К примеру можем в таблице Клиенты можем быстро вывести колонку Кол-во покупок, присоединив таблицу заказов и посчитав количество записей по конкретному клиенту. Вычисления оптимизированы. Не получится такого. что на каждую из записей мы делаем дополнительный запрос.
4. Вычисляемые поля. Тут можно реализовать любую PHP логику. Посчитать средний чек каждого клиента, например. Здесь указываем путь к файлу, который что-то посчитает и вернет ответ. По сути сниппет, только файловый. Желательно не использовать запросы к базе, потому что логика будет исполняться для каждой записи таблицы.
5. Поля-действия. Здесь настраиваем кнопки действий. Здесь предусмотрена отдельная логика с подключением JS скриптов. Подробнее будет в документации.
Клиенты и личный кабинет
Модель msCustomer — полноценная сущность
— Отдельная от modUser система клиентов
— Токены авторизации (API, refresh, magic links)
— Адреса доставки с полем is_default
— GDPR поля (consent, marketing)
Личный кабинет клиента (Frontend)
— Страница адресов (/cabinet/addresses)
— Установка адреса по умолчанию
— Удаление с подтверждением
— Страница заказов (/cabinet/orders)
— Фильтрация по статусу
— Пагинация
— Детальный просмотр заказа
— Web API для управления адресами
Система авторизации клиентов
— RegisterService с автологином после регистрации
— AuthManager для входа/выхода
— TokenMiddleware с поддержкой сессии и API токенов
— RateLimiter для защиты от брутфорса
Полноценное управление клиентами из админки
Из интересного, постарался реализовать подключаемые сервисы авторизации. По умолчанию авторизация через email + пароль. Но можно подключить например SMS, или комбинировать способы. Подробнее будет описано в документации
Были и неудачные работы, которые после проработки и долгого обсуждения пришлось выбросить. Не удалось полностью убрать логику из XPDO файлов.
В идеальной картине программирования Модели должны делать запросы в базу и на этом все. Модель никогда не знает о вышестоящих контроллерах, сервисах, репозиториях.
Вся логика обычно лежит в сервисе или репозитории. Они по мере необходимости дергают модели для операцией с базой данных.
В MODX3 совсем другая логика. Она строится вокруг моделей. Внутри много бизнес-логики. И, к сожалению, эта архитектура наследуюется в самых крупных классах Минишоп msProduct и msCategory. MODX дергает эти xpdo модели напрямую. Нет возможности нормально переопределить поведение. Все что удалось сделать это вынести бизнес-логику в подключаемые сервисы. Но модель все равно подключает сервис, знает о нем и как бы им распоряжается, находясь выше по статусу.
Фронтенд — шаблоны и чанки.
Для всех страниц подготовил обновленные примеры шаблонов и чанков в более-менее современном визуале.
Когда релиз
По сути следующая итерация правок — заключительная перед выходом в Beta версию и выкладкой в modstore
Вот что я запланировал сделать:
1. Работа с заказом в админке. Перевожу страницу заказов на VUE. Делаю таблицу и окно заказа конфигурируемым. Планирую переделать логгирование заказа. Оптимизация PHP.
2. Хотелось бы и другие странички доработать, перевести их на VUE. Например Настройки производителей, статусы и так далее. Это не слишком критично, может и позже сделаю.
3. Еще немного поработаю с чанками и шаблонами. Пока не до конца доволен. Нужны доработки.
4. Тесты мультиязычности и мульти-контекстов.
5. Самое важное — документация.
По ощущениям — думаю мне понадобится около двух месяцев на. Возможно получится сделать сообществу подарок к новому году. Тут многое зависит от загруженности на работе.
Далее приступаю к работе над обновлением mSearch. Также запланирована вообще вся линейка жизненно важных компонентов для построения большого интернет-магазина.
Поблагодарить автора
Отправить деньги
Комментарии: 3
Для желающих протестировать — создал релиз в GitHub. Там можно скачать готовый транспортный пакет.
С визуальным конструктором полей прям огонь. Горжусь тобой!)))
А вообще покупатели могут быть связаны с пользователями MODX? Ведь порой надо будет добавить магазин на сайт, где уже есть личный кабинет и пользователи. Или наоборот на сайте с магазином может быть и другой функционал, завязанный на юзеров
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.