miniShop2 3.0 Alpha релиз.

Друзья впервые за 5 лет, после версии 2.4 команда minishop2 пришла к кардинальным, не косметическим изменениям, и впервые за всю историю компонента мы готовим к выпуску мажорный релиз.



Введение



Внимание эта заметка предназначена для опытных разработчиков сайтов и компонентов для minishop2.
Релиз пока не доступен для общей установки, и находится в отдельной ветке репозитория. Это альфа релиз — то есть, он не подходит для продакшена. Задача Альфа релиза — пощупать общую реализацию идеи. На этом этапе мы еще можем что-то выбросить, что-то добавить, а можем вообще по другому реализовать идею, что уже произошло. Первый альфа релиз был представлен в закрытом чате разработчиков, и после обсуждения было принято решение изменить реализацию.

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

Что нового



Меняем структуру файлов.

Для затравки начнем с того, что все контроллеры-хэндлеры будут вынесены за пределы каталога модели в новый каталог handlers. Каталог models/ предназначен для хранения классов управляющих записями базы данных. Хранить в этом каталоге логику — некорректно. Так же как, например, некорректно хранить логику в шаблонах и тем более производить там какие-либо вычисления, как многие любят делать.

Что сделано:

1. Добавлен каталог /components/nminishop2/handlers/
2. В этот каталог вынесены файлы

  • mscarthandler
  • msdeliveryhandler
  • mspaymenthandler
  • msorderhandler
3. В каталоге /components/nminishop2/model/minishop2/, на прежнем месте нахождения указанных файлов сделаны временные заглушки следующего содержания

<?php

//Deprecated: use handlers from catalog core/components/minishop2/handlers/
require_once dirname(__FILE__, 3) . '/handlers/mscarthandler.class.php';
Такой подход позволит при обращении к любому хэндлеру по старому адресу перенаправить запрос и не вызовет ошибку. Обратите внимание что файлы помечены как Deprecated и в следующих релизах будут удалены совсем.

Рекомендация:

Проследите что ваши компоненты (если они как-то работают с контроллерами minishop2) ссылаются на корректный путь, а лучше перед загрузкой файлов контроллеров проверяют на существование файлы классов по обновленному пути

Проследите что классы вашего сайта, в особенности контроллеры в каталоге components/minishop2/custom/ которые наследуют и расширяют стандартные контроллеры minishop2 — проверяют на существование файлы классов перед их загрузкой и в первую очередь проверяют на существование каталог handlers/

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

$newBaseCartHandler = dirname(__FILE__, 3) . '/handlers/mscarthandler.class.php';
$oldBaseCartHandler = dirname(__FILE__, 3) . '/model/minishop2/mscarthandler.class.php';

if (!class_exists('msCartInterface')) {
    if (file_exists($newBaseCartHandler)) {
        require_once $newBaseCartHandler;
    } else {
        require_once $oldBaseCartHandler;
    }
}

Корзину и временные поля заказа больше не обязательно хранить в сессии.

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

В современном мире часто приходится реализовывать фронт на базе JS фреймворков, принимать заказ из мобильного приложения или через API из других источников (сторонние маркетплейсы, например). И не всегда удается правильно поднять сессию, чтобы при каждом обращении к API минишопа добавлять изменять уже существующую корзину или дополнять заполняемый заказ.

Возникла идея избавиться от сессий совсем и хранить данные в базе, что мы собственно, и сделали.

Переписали классы корзины и заказа в более абстрактном стиле, не указывая напрямую, где хранить временную информацию. Теперь у нас есть подключаемые хранилища, в каждом из которых реализована своя логика хранения и обработки информации.

Было примерно так:
$_SESSION[minishop2]['cart'][$key] = $cartItem;

Стало вот так
$this->storageHandler->add($cartItem);

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

Также добавлено новое хранилище — База данных. Вы без каких-либо проблем можете добавлять свои хранилища, например файловый вариант (что-то вроде кэша).

Расскажу немного подробнее о том, как работает хранилище реализованное для базы данных.

Был добавлен новый статус заказа «Оформляется» — «Processed»
При первом добавлении товара в корзину, создается пустой заказ с таким статусом. По мере обновления корзины и оформления заказа данные обновляются и в конце концов он переходит в статус Новый заказ

Здесь появляется дополнительное весомое преимущество подхода. Есть возможность видеть корзины еще до оформления заказа. Это полезно для аналитики. Также можно видеть брошенные корзины и предпринимать необходимые действия, имея контактные данные клиента.

Второе весомое преимущество подхода — это возможность переключаться между устройствами.
Авторизованный клиент, начав набирать корзину на телефоне, без труда переключается на компьютер и видит там свою корзину продолжая оформлять заказ.
Думаю, многие оценят!

Ну и самое главное — ради чего все затевалось — теперь стало легче работать из сторонних приложений используя API минишопа.
К примеру я могу через свое мобильное приложение кидать товары в корзину и не париться о том как восстановить на стороне сервера сессию, которая по идее при каждом запросе поднимается заново с новым идентификатором. Не нужно изобретать велосипеды и хранить сессию где-то в свойствах юзера. И так далее.

Точно также я могу обращаться удаленно к сайту из localhost разрабатывая локально очередную кастомную админку для ms2 на каком нибудь vue nuxt и не париться насчет сессии.

Тип хранилища переключается через системную настройку ms2_tmp_storage
Из коробки доступны две опции — db и session

Рекомендация:

Уважаемые разработчики — Вам обязательно нужно подготовить свои сайты и компоненты для использования нашего обновления!

Основное на что нужно обратить внимание — это использование сессии напрямую.

Я часто встречаю (да и сам писал) код следующего содержания
//  Это условный плагин который пересчитывает корзину
$cart = $_SESSION['minishop2']['cart'];
// Здесь что-нибудь делаем с корзиной, меняем цену одного из товаров например
$cart[$key]['price'] =  1000;
// Пишем обновление в корзину
 $_SESSION['minishop2']['cart'] = $cart;

Теперь придется учитывать вариант, при котором корзина или поля заказа хранятся не в сессии.
На самом деле ничего нового делать не нужно, просто воспользоваться API минишопа, который давным-давно придуман. Давайте перепишем код по правильному

$ms2 = $modx->getService('minishop2');
$ms2->initialize('web');
$cart = $ms2->cart->get();
// Здесь что-нибудь делаем с корзиной, меняем цену одного из товаров например
$cart[$key]['price'] =  1000;
// Пишем обновление в корзину
$ms2->cart->set($cart);

Как можно заметить суть не изменилась, но код стал более абстрактным и отлично отработает уже с любым типом хранилища информации.
В общем сайты и компоненты нужно подготовить, переписав прямое использование сессии на методы API

Требуется ваша помощь


Друзья — так как это обновление очень серьезное — не хочется торопиться с релизом.
Приглашаю вас принять участие в тестировании.
Вы можете сделать следующее:

1. Развернуть простые тестовые сайты, установить minishop2 из отдельной ветки и просто протестировать работу с корзиной и заказом. Причем как в режиме session так и в режиме db
2. Развернуть dev версии своих действующих сайтов и установить обновление туда. Реальные кейсы — позволят собрать больше ошибок
3. Ну и конечно поучаствовать непосредственно в коде проекта. Почти наверняка есть неучтенные нюансы, о которых не подумали.

Подробнее о методике тестирования будет отдельная заметка.

По просьбам создан сбор на дальнейшее развитие miniShop2
Огромное спасибо, всем кто поддерживает и донатит!
Николай Савин
17 октября 2021, 10:58
modx.pro
1
2 076
+29
Поблагодарить автора Отправить деньги

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

Василий Наумкин
18 октября 2021, 10:21
+1
Я бы предложил вместо miniShop2 3.0 сделать просто miniShop3

Это сняло бы массу проблем с расположением файлов, переездом рабочих сайтов и разработкой дополнений. Тем более, что домен для него давно куплен и ждёт своего часа — minishop3.com
    Николай Савин
    18 октября 2021, 10:25
    +1
    Вась обсуждали, даже голосовали — решили вот таким путем пойти потому что
    1. semver
    2. Устоявшийся бренд
    3. В коде практически всех компонентов, расширяющих минишоп, плагинов, расширенных классов getService(minishop2) и $ms2 фигурируют.
    4. У нас есть большая задумка по более глобальному рефакторингу, если она выстрелит — там может переименуем.
      Николай Савин
      18 октября 2021, 10:29
      +1
      Еще дополню — в целом решили на второй ветке MODX оставаться на текущем именовании (по крайней мере пока мелкими шажками правки вносим), а на MODX3 все равно всю экосистему переделывать — там уже ms3 сделать
    Наумов Алексей
    19 октября 2021, 09:04
    +1
    Николай, добрый день! Раз уж мажорная версия, может быть стоит и вот с этим навести порядок сразу? modx.pro/help/21786
    Не так давно я писал об этой неоднозначности с email и phone в miniShop2.
      Николай Савин
      19 октября 2021, 09:12
      +2
      Привет. Не хотелось бы смешивать в одном релизе разные темы. Этот релиз про хранение временных данных.
      У меня пока задача сломать людям сайты только одним способом )).
      Дойдут руки и до твоего вопроса, он зафиксирован и висит в Issue. Как и более 70 других.
      Идем по порядку, чтобы проще было искать проблемы.
      А мажорные релизы теперь часто будут.
      Навскидку в ближайшее время будет полностью изменен JS API (вернее он в принципе появится), что повлечет за собой полное изменение JS и появление продвинутой мини-корзины и возможность работать из JS фремворков
        Наумов Алексей
        19 октября 2021, 09:41
        0
        окей) хорошо. Предположил, что частые мажорные релизы тоже не гуд, они ломают людям сайты, заставляют или многое переделывать или «забивать» на обновление компонента. Но и без них, конечно, никуда
          Николай Савин
          19 октября 2021, 09:44
          0
          Щас удивлю наверное кого-то, но обновляться в общем то не обязательно.
          Мажорные релизы предназначены для новых сайтов.
          А старый сайт если работает на текущей версии — пусть себе работает, зачем его обновлять.
            Наумов Алексей
            19 октября 2021, 09:54
            +1
            В общем да… в частном нет… к сожалению (
            1. Проблемы безопасности, находят уязвимость, в старой версии (не важно чего, MODX или miniShop) никто исправлять не будет — обновляйте!
            2. Проблема совместимости со сторонними компонентами. Подключен у нас модуль интеграции со СДЭК, обновили они свое API, компонент соответствующий для MODX обновился, но он теперь работает только на свежем miniShop, обновляйте!
      Алексей
      21 октября 2021, 07:43
      0
      может быть глупый вопрос — но что с дополнениями минишопа? ли они работать на новой версии? тот же mfiltre2 и office — либо надо ждать пока авторы перепишут их под новую версию?
        Николай Савин
        21 октября 2021, 08:31
        +3
        Алексей вы вообще анонс читали? Изменения коснулись корзины и системы оформления заказа. Какое к этому имеют отношение офис и фильтр?
        Дополнения касающиеся темы — нужно тестировать и адаптировать (если будут найдены проблемы).
        И я специально в этом посте подробно описываю что изменяется, на что обратить внимание — чтобы у авторов компонентов была подробная информация
        R2m0x94 (Vasily)
        28 октября 2021, 15:46
        0
        У меня такая ошибка в журнале новой версии minishop2 2.9.3-pl, PHP 8.0, MODX 2.8.3-pl:
        [2021-10-28 15:26:20] (ERROR @ /core/model/modx/modx.class.php: 1677) [OnMODXInit]
        Deprecated: Required parameter $entry follows optional parameter $action in /core/components/minishop2/model/minishop2/minishop2.class.php on line 918
        Только распаковался, у кого-то было также?
          Николай Савин
          28 октября 2021, 15:49
          +2
          Это не совсем ошибка ms2. Здесь дело в PHP8.
          Насколько я знаю MODX в целом пока не готов к PHP8.
          Справедливости ради в данном случае MODX не при чем, тут нужно вносить правки в minishop2.
          Это уже запланировано и впереди полный рефакторинг кода
            R2m0x94 (Vasily)
            28 октября 2021, 16:05
            0
            Временно задал в 918 строке $entry = 0, вроде ошибки нет))
              Николай Савин
              28 октября 2021, 16:07
              0
              Корректнее было бы совсем убрать значение по умолчанию. Ошибка в том, что такие параметры со значениями по умолчанию должны стоять в конце.
          Константин Ильин
          24 ноября 2021, 16:03
          0
          miniShop2 2.9.3-pl
          MODX Revolution 2.8.3-pl
          Google Chrome последний
          ctrl+F5 нажимал

          Что-то с z-index у списка выбора опции, не могу выбрать опции

          prnt.sc/20s4etp
            Николай Савин
            24 ноября 2021, 16:12
            0
            Это компонент extJS встроенный в modx — по идее не к минишопу вопросы. ms2 просто вызывает компонент
              Константин Ильин
              24 ноября 2021, 16:16
              0
              а где можно проверить компонент, точнее говоря где такой же вызов компонента?

              Например здесь норм
              prnt.sc/20s66rs

              Видимо модальное окно выше по z-index
            Евгений Лазарев
            19 января 2022, 18:49
            0
            Добрый день уважаемые разработчики. У меня к вам вопрос: есть ли возможность в новой версии усовершенствовать код в default.js minishop2.Order.add
            $field.val(response.data[key]).removeClass('error').closest(miniShop2.Order.inputParent).removeClass('error');
            Дело в том что иногда нужно добавить свои radio, но изза этого кода получается что всем radio в аттрибут value пишется новое значение.
              Николай Савин
              20 января 2022, 00:18
              0
              Вы без проблем можете использовать свою логику внутри собственного доработанного файл скриптов. Он подключается через соответствующую системную настройку.
                Евгений Лазарев
                20 января 2022, 00:39
                0
                Да я знаю. Просто я топлю за оригинальный файл, к тому же я пока не смог придумать ситуацию где бы для input[type=radio] нужно было применять действия, которые написаны в файле. Даже для delivery и payment сделаны соответствующие исключения. По факту на мой взгляд написано верно, но не для такого типа input. Есть ли возможность указать исключение для них?
                  Николай Савин
                  20 января 2022, 12:22
                  0
                  В этом году весь JS будет полностью переписан на современный стиль. Без jQuery зависимости, возможно в модульном решении, при котором нужные модули подключаются по мере необходимости. Выбросим галерею, которой все равно никто не пользуется. Появится JS API. Будут, думаю, нативные события, а не колбэки. Ну и так далее. Не вижу смысла переписывать или как то модифицировать то, что есть сейчас. Там все целиком пора выбрасывать.
            Алекс Назаренко
            09 августа 2022, 14:38
            0
            Как теперь можно в кастомном классе msCartHandler c помощью функции change отправить в корзину новую цену при изменении количества товара?
            Раньше вопрос решался добавлением однойстроки
            $this->cart[$key]['price'] = 100;
            А теперь, что дописать, чтобы изменить цену на 100?
              Николай Савин
              09 августа 2022, 20:08
              0
              Метод change по заложенной в него логике отвечает только за изменение количества.
              Чтобы изменить цену — корректнее будет использовать метод set, передав туда исправленную корзину.
                Алекс Назаренко
                09 августа 2022, 21:55
                0
                Так а где эту корзину исправлять? Она исправляется в
                public function change($key, $count)
                где и проверяется количество товара, от которого зависит цена.
                Мне нужно именно из этого метода отправить, до обновления это делалось легко.
                  Николай Савин
                  10 августа 2022, 11:44
                  +2
                  У вас же кастомный класс корзины. Значит в любом месте, где это удобно по вашей бизнес-логике сделать, пишите примерно следующее
                  // сохраняете корзину в переменную
                  $cart = $this->get();
                  // Тут меняете корзину
                  $cart[$key]['price'] = 100;
                  // Перезаписываете корзину
                  $this->set($cart);
                  И это совсем не обязательно делать внутри класса корзины. Можно использовать функционал плагинов. Только там будет немного другое обращение к корзине через $ms2->cart->get() и set() соотвественно
                    Алекс Назаренко
                    10 августа 2022, 14:27
                    0
                    Спасибо! Плагины лишний раз использовать не люблю.
              Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
              27