Всего 125 667 комментариев

Александр Туниеков
1 минута назад
0
Кто реально внедрил MODX с Vue. js — каков опыт?
Опыт — реактивные переменные благословение и проклятие Vue. С ними можно делать почти мнгновенно реагирующий интерфейс и неприятность что в них не всегда оказывается то что нужно. Где то в коде именил или не изменил не так как нужно и приложение ведет себя не так как нужно. Отследить изменения тяжело особенно если меняешь чужой код или код ИИ
Александр Туниеков
25 минут назад
0
Я делаю miniERP систему на модекс. ИИ помогает значительно. Но с ИИ лучше делать когда сам понимаешь как сделать. Нейросеть не догоняет весь контекст. И сочиняет на ходу чтобы как-бы выполнить задачу. Правда у меня нейросеть хотя бы пытается что-то сделать, а люди сразу в ступор впадают :-). Непривычный контекст задач и тяжело въехать.
Я делаю систему с нейросетью используя modExtra и PVExtra, так как IDE заточены под файлы и в базу не лезут. А в MODX пользовательский код обычно в базе. То есть ставлю чистый MODX. Делаю на нем ЧПУ и делаю компоненты которые заполняют сайт. Возможно имеет смысл подключить к нейросети MCP MySQL и чтоб нейросеть напрямую редактировала страницы и шаблоны. Чанки, сниппеты и тв в последнее время не использую. Вместо сниппетов vue компоненты к которым чанки не особо прикрутишь. А вместо тв проще нужные таблицы сразу писать.
Мне проше сразу писать компоненты. Некоторые потом можно отдельно выкладывать. И проще в прод вносить изменения. Просто поставил компонент и нужные правки применились. И не надо делать деплой всего сервера. Правки по компонентам и нужно поставить лишь тот компонент в котором изменения.

С нейросеть у меня 2 метода писать код:
1. Точечное промт-програмирование. Например, пишешь промпт: здесь отсортируй массив по возрастанию ранга наряда. И нейросеть вставляет нужный код.
2. Вайб-кодинг. Есть задача которую непонятно как сделать и пишешь, например, нужно сделать дополнительные фильтры чекбоксы которые выводят список значений в таблице и при выборе которых в таблице фильтруется по этим выбранным значениям. И нейросеть сама разбирается что сделать и пишет код. Такой промпт я как-то задавал и потом 3 часа разбирался почему основные фильтры не работают. Оказалось что нейросеть решила, что если есть допфильтры, то основные не нужны :-).

3 месяц писал с Kilo Code для VSCode. Но постепенно работа через API Claude стала забирать все больше денег. Сейчас использую Claude Code для VSCode с подпиской MAX. Она втрое дешевле должна выходить. Вчера сочинял с ним план внедрения в miniERP продажи перепродоваемых товаров (вместе с товарами которые мы изготавливаем). Перед использованием вайб-кодинга лучше с ИИ сочинить план разработки.

Ну вкратце так. Более подробно пока желания писать нет. Хотя есть моменты которые хочется обсудить или написать статьи, но прям сейчас только то что написал.
W.H.I.T.E
1 час назад
0
Когда примерно ожидать версию под MODX3?
Тодор
3 часа назад
0
Ето ты сделал?
public function getReceiverId() {
  error_log("🔥🔥🔥 getCustomerId() НАЧАЛО 🔥🔥🔥");
  $customer = null;
  $response = $this->ms2->invokeEvent('msOnBeforeGetOrderCustomer', [//вместо $this->
    'order' => $this,//Вместо $this->order,
    'customer' => $customer,
  ]);
  if (!$response['success']) {
    return $response['message'];
  }

  if (!$customer) {
    $data = $this->get();//Вместо $this->order->get();
    
    ...
      $this->set($data);//Вмесо $this->order->set($data);
    ...
  }

  $response = $this->ms2->invokeEvent('msOnGetOrderCustomer', [//Вместо $this->
    'order' => $this, // Вместо $this->order,
    'customer' => $customer,
  ]);
  if (!$response['success']) {
    return $response['message'];
  }

  return $customer instanceof modUser ? $customer->get('id') : 0;
}
возможно что-то упустил
Дмитрий
3 часа назад
0
ух, спасибо за разъяснения. Т.е. фактически понятие «регистрация службы» это просто изменение системных настроек?

с разным расположением файла в зависимости от версии, я уже споткнулся на этом моменте когда подключал свою службу доставки, кстати, в мануале, как раз таки не правильно указано расположения файла (по всей видимости для старой версии)
Я разобрался почему у меня не подключался мой класс, в системных настройках в значении переменной ms2_order_handler_class, у меня было указано «my_OrderHandler » с пробелом на конце, очень было обидно осознать это, когда я два дня пытался разобраться, чой-то мой класс не подключается.

Теперь что касается, кастомного класса. Или, наверное даже больше кастомного метода.

Я начал с того что поменял исходники, и собственно, все у меня работало так как надо.
Телефон приводился к нужному формату, вместо емейла записывался номер телефона, и вообще жизнь прекрасна и удивительна, но!
Когда, все же заработал мой класс, и я сделал, как Вы советовали:
я скопировал метод submit, в нем изменил $user_id = $this->ms2->getCustomerId() на $user_id = $this->getReceiverId();

и новый метод, поменял у него название на getReceiverId()…
тут все работать перестало.

По сути в исходниках я изменял только метод getCustomerId
И был совершенно уверен, что тут у меня не возникнет ни каких проблем.

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

Помогите, я снова в тупике.
Тодор
Вчера в 23:53
0
Етот кусок кода отвечает за то что бы менялась настройка ms2_services
<?php
if ($miniShop2 = $modx->getService('miniShop2')) {
  $miniShop2->addService('order', 'my_OrderHandler',
      '{core_path}components/minishop2/custom/order/my_msorderhandler.class.php');
}
После чего у тебя ms2_services должен быть таким
{"cart":[],"order":{"my_OrderHandler":"{core_path}components\/minishop2\/custom\/order\/my_msorderhandler.class.php"},"payment":[],"delivery":{"mydelivery":"{core_path}components\/minishop2\/custom\/delivery\/my_msdeliveryhandler.class.php"}}
Тебе надо делать только одно из двух либо регистировать клас через консоль либо в сис. настройках.

В зависимости от версии minishopа может быть разный путь к msOrderHandler, убедись что етот файл существует
require_once MODX_CORE_PATH . 'components/minishop2/handlers/msorderhandler.class.php';
А еще в submit ты поменял $user_id = $this->ms2->getCustomerId(); на $user_id = $this->getReceiverId(); Но новый метод ты не назвал getReceiverId
Futuris
Вчера в 10:34
+1
В какое славное время я взялся за изучение кода)) Только выучил элементарную базу PHP, как выясняется, что это скоро и не нужно никому будет). Расходимся! Правда пока, по опыту общения с нейронками я вижу, что даже элементарные знания помогают и сильно сокращают время. А там, где полагаешься только на робота, авось как-то вывезет сам — там тратится неимоверное количество итераций, чтобы получить какой-то рабочий результат.
SYAN
Вчера в 01:40
0
Далее код оставил без изменений
<script type="text/javascript">
    // <![CDATA[
    {literal}
    Ext.onReady(function () {
        var fld = MODx.load({
            {/literal}
            xtype: 'textfield',
            applyTo: 'tv{$tv->id}',
            width: '99%',
            id: 'tv{$tv->id}',
            enableKeyEvents: true,
            allowBlank: {if $params.allowBlank == 1 || $params.allowBlank == 'true'}true{else}false{/if},
            value: '{$tv->value}',
            {literal}
            listeners: {'change': {fn: MODx.fireResourceFormChange, scope: this}},
        });
        Ext.getCmp('modx-panel-resource').getForm().add(fld);
        MODx.makeDroppable(fld);
    });
    {/literal}
    // ]]>
</script>

{$fields = [
'title' => $_config.videogallery_field_title,
'desc' => $_config.videogallery_field_desc,
'image' => $_config.videogallery_field_image,
'video' => $_config.videogallery_field_video,
'videoId' => $_config.videogallery_field_videoId,
'videoDuration' => $_config.videogallery_field_videoDuration
]}
{foreach from=$fields key=name item=item}
    {if $item != ''}
        {if substr($item, 0,3) == 'tv.'}
            {$vg_fields[$name] = str_replace('tv.', '', $item)}
            {$input_ids_data = "tv`$modx->getObject('modTemplateVar', ['name'=>$vg_fields[$name]] )->id`"}

            {if $input_ids_data != 'tv' AND $input_ids_data != ''}
                {$input_ids[$name] = $input_ids_data}
            {/if}
        {else}
            {$vg_fields[$name] = $item}
            {$input_ids[$name] = "modx-resource-`$vg_fields[$name]`"}
        {/if}
    {/if}
{/foreach}

<script type="text/javascript">
    // <![CDATA[
    Ext.onReady(function () {
        if (typeof vgHandlers == 'undefined') {
            vgHandlers = {
                /* */
            };
        }
        vgHandlers['{$tv->id}'] = new videoGalleryHandler({
            tv: '{$tv->id}',
            tvid: '{$tvid}',
            resource: {$modx->resource->id},
            actionUrl: MODx.config.assets_url + 'components/videogallery/connector.php?HTTP_MODAUTH=' + MODx.siteId + '&wctx=mgr&action=mgr/gallery/handle',
            selectors: {
                tvInput: '#tv{$tv->id}',
            },
            callbacks: {
                success: function (resp) {
                    var element = {
                        /* */
                    };
                    element['{$tv->id}'] = {
                        /* */
                    };

                    {foreach from=$fields key=name item=field}
                    {if $field != '' AND $field != 'tv'}
                    if (resp.object.hasOwnProperty('{$name}')) {
                        element['{$tv->id}']['{$name}'] = document.querySelector('#{$input_ids[$name]}');
                        if (element['{$tv->id}']['{$name}']) {
                            element['{$tv->id}']['{$name}'].value = resp.object['{$name}'];
                        }
                    }
                    {/if}
                    {/foreach}
                },
                reset: function () {
                    var element = {
                        /* */
                    };
                    element['{$tv->id}'] = {
                        /* */
                    };

                    {foreach from=$fields key=name item=field}
                    {if $field != '' AND $field != 'tv'}
                    element['{$tv->id}']['{$name}'] = document.querySelector('#{$input_ids[$name]}');
                    if (element['{$tv->id}']['{$name}']) {
                        element['{$tv->id}']['{$name}'].value = '';
                    }
                    {/if}
                    {/foreach}
                },
            },
        });
    });
    // ]]>
</script>

{* Fix "Smarty Compiler: Syntax error {/foreach} unclosed {foreach} tag" *}
{foreach from=$fields key=name item=field}
{/foreach}
SYAN
Вчера в 01:38
0
Функция сохранения
<script type="text/javascript">
// <![CDATA[
Ext.onReady(function () {
    // Сохраняем исходные значения при загрузке
    const originalValues = {
        title: document.getElementById('vgTitle_{$tv->id}').value,
        desc: document.getElementById('vgDesc_{$tv->id}').value,
        video: document.getElementById('vgVideo_{$tv->id}').value,
        videoId: document.getElementById('vgVideoId_{$tv->id}').value,
        image: document.getElementById('vgImage_{$tv->id}').value,
        videoDuration: document.getElementById('vgVideoDuration_{$tv->id}').value
    };

    window.compareAndSave = function(tvId) {
        const currentValues = {
            title: document.getElementById('vgTitle_' + tvId).value,
            desc: document.getElementById('vgDesc_' + tvId).value,
            video: document.getElementById('vgVideo_' + tvId).value,
            videoId: document.getElementById('vgVideoId_' + tvId).value,
            image: document.getElementById('vgImage_' + tvId).value,
            videoDuration: document.getElementById('vgVideoDuration_' + tvId).value
        };

        // Проверяем, есть ли изменения
        let hasChanges = false;
        for (const key in currentValues) {
            if (currentValues[key] !== originalValues[key]) {
                hasChanges = true;
                break;
            }
        }

        if (!hasChanges) {
            alert('Нет изменений для сохранения.');
            return;
        }

        // Формируем новый JSON
        const newJson = JSON.stringify(currentValues);

        // Обновляем скрытое поле
        document.getElementById('tv' + tvId).value = newJson;

        // Сигнализируем MODX об изменении
        if (typeof MODx !== 'undefined' && MODx.fireResourceFormChange) {
            MODx.fireResourceFormChange();
        }

        alert('Данные сохранены!');

        // Обновляем исходные значения (чтобы следующие изменения сравнивались корректно)
        Object.assign(originalValues, currentValues);
    };

    // Интеграция с videoGalleryHandler
    if (typeof vgHandlers !== 'undefined' && vgHandlers['{$tv->id}']) {
        vgHandlers['{$tv->id}'].callbacks.success = function(resp) {
            // Обновляем поля формы
            document.getElementById('vgVideo_{$tv->id}').value = resp.object.video || '';
            document.getElementById('vgVideoId_{$tv->id}').value = resp.object.videoId || '';
            document.getElementById('vgImage_{$tv->id}').value = resp.object.image || '';
        };
    }
});
// ]]>
</script>

<style>
.videogallery-wrapper { padding:10px; border:1px solid #ddd; border-radius:4px; }
.videogallery-fields div { margin:10px 0; }
label { display:inline-block; width:120px; font-weight:bold; }
input,textarea { width:100%; padding:5px; box-sizing:border-box; }
</style>
Олег Захаров
Вчера в 01:17
0
По этому вопросу тоже думаю — создал вопрос тут
Николай Савин
20 февраля 2026, 20:13
0
Не нужно меня поддерживать в данном конкретном случае. Прошу убрать лишнее
Дмитрий
20 февраля 2026, 19:28
0
В общем убил целый день, но… так у меня ничего и не вышло.
не могу зарегистрировать класс.

содержание самого файла my_msorderhandler.class.php:

<?php
if (!class_exists('msOrderHandler')) {  // проверяем интерфейс заказа
    require_once MODX_CORE_PATH . 'components/minishop2/handlers/msorderhandler.class.php';
}

class my_OrderHandler extends msOrderHandler {  // implements msOrderInterface не нужен
    public function submit($data = [])
        {
            
            $response = $this->ms2->invokeEvent('msOnSubmitOrder', [
                'data' => $data,
                'order' => $this,
            ]);
            if (!$response['success']) {
                return $this->error($response['message']);
            }
            if (!empty($response['data']['data'])) {
                $this->set($response['data']['data']);
            }
    
            $response = $this->getDeliveryRequiresFields();
            if ($this->ms2->config['json_response']) {
                $response = json_decode($response, true);
            }
            if (!$response['success']) {
                return $this->error($response['message']);
            }
            $requires = $response['data']['requires'];
    
            $errors = [];
            foreach ($requires as $v) {
                if (!empty($v) && empty($this->order[$v])) {
                    $errors[] = $v;
                }
            }
            if (!empty($errors)) {
                return $this->error('ms2_order_err_requires', $errors);
            }
    
            $user_id = $this->getReceiverId();
            if (empty($user_id) || !is_int($user_id)) {
                return $this->error(is_string($user_id) ? $user_id : 'ms2_err_user_nf');
            }
    
            $cart_status = $this->ms2->cart->status();
            if (empty($cart_status['total_count'])) {
                return $this->error('ms2_order_err_empty');
            }
    
            $delivery_cost = $this->getCost(false, true);
            $cart_cost = $this->getCost(true, true) - $delivery_cost;
            $num = $this->getNewOrderNum();
    
            /** @var msOrder $msOrder */
            $msOrder = $this->storageHandler->getForSubmit(
                compact('user_id', 'num', 'cart_cost', 'cart_status', 'delivery_cost')
            );
    
            $response = $this->ms2->invokeEvent('msOnBeforeCreateOrder', [
                'msOrder' => $msOrder,
                'order' => $this,
            ]);
            if (!$response['success']) {
                return $this->error($response['message']);
            }
    
            if ($msOrder->save()) {
                $response = $this->ms2->invokeEvent('msOnCreateOrder', [
                    'msOrder' => $msOrder,
                    'order' => $this,
                ]);
                if (!$response['success']) {
                    return $this->error($response['message']);
                }
    
                if ($this->storage === 'session') {
                    $this->ms2->cart->clean();
                    $this->clean();
                }
                if (empty($_SESSION['minishop2']['orders'])) {
                    $_SESSION['minishop2']['orders'] = [];
                }
                $_SESSION['minishop2']['orders'][] = $msOrder->get('id');
    
                // Trying to set status "new"
                $status_new = $this->modx->getOption('ms2_status_new', null, 1);
                $response = $this->ms2->changeOrderStatus($msOrder->get('id'), $status_new);
                if ($response !== true) {
                    return $this->error($response, ['msorder' => $msOrder->get('id')]);
                }
    
                // Reload order object after changes in changeOrderStatus method
                /** @var msOrder $msOrder */
                $msOrder = $this->modx->getObject('msOrder', ['id' => $msOrder->get('id')]);
    
                /** @var msPayment $payment */
                $payment = $this->modx->getObject(
                    'msPayment',
                    ['id' => $msOrder->get('payment'), 'active' => 1]
                );
                if ($payment) {
                    $response = $payment->send($msOrder);
                    if ($this->config['json_response']) {
                        @session_write_close();
                        echo is_array($response) ? json_encode($response) : $response;
                        die();
                    }
                    if (!empty($response['data']['redirect'])) {
                        $this->modx->sendRedirect($response['data']['redirect']);
                    }
                    if (!empty($response['data']['msorder'])) {
                        $redirect = $this->modx->context->makeUrl(
                            $this->modx->resource->id,
                            ['msorder' => $response['data']['msorder']]
                        );
                        $this->modx->sendRedirect($redirect);
                    }
                    $this->modx->sendRedirect($this->modx->context->makeUrl($this->modx->resource->id));
                } else {
                    if ($this->config['json_response']) {
                        return $this->success('', ['msorder' => $msOrder->get('id')]);
                    }
                    $redirect = $this->modx->context->makeUrl(
                        $this->modx->resource->id,
                        ['msorder' => $msOrder->get('id')]
                    );
                    $this->modx->sendRedirect($redirect);
                }
                return $this->success();
            }
    
            return $this->error();
        }
        
        
        public function getCustomerId() {
    error_log("🔥🔥🔥 getCustomerId() НАЧАЛО 🔥🔥🔥");

        $customer = null;

        $response = $this->invokeEvent('msOnBeforeGetOrderCustomer', [
            'order' => $this->order,
            'customer' => $customer,
        ]);
        if (!$response['success']) {
            return $response['message'];
        }

        if (!$customer) {
            $data = $this->order->get();
            $email = $data['email'] ?? '';
            $receiver = $data['receiver'] ?? '';
            $phone = $data['phone'] ?? '';
            
            // Функция для приведения телефона к международному формату +КодСтраныНомер
            $formatPhone = function($phone) {
                if (empty($phone)) return '';
                
                // Удаляем все нецифровые символы
                $phone = preg_replace('/[^0-9]/', '', $phone);
                
                // Определяем код страны по умолчанию (Россия)
                $defaultCountryCode = '7';
                
                // Если номер начинается с 8 (Россия)
                if (substr($phone, 0, 1) == '8') {
                    $phone = $defaultCountryCode . substr($phone, 1);
                }
                // Если номер без кода (10 цифр) - добавляем код по умолчанию
                elseif (strlen($phone) == 10) {
                    $phone = $defaultCountryCode . $phone;
                }
                // Если номер начинается с 7 (уже есть код России)
                elseif (substr($phone, 0, 1) == '7' && strlen($phone) == 11) {
                    // Оставляем как есть
                }
                // Если номер с другим кодом страны
                elseif (strlen($phone) > 11 || (strlen($phone) == 11 && substr($phone, 0, 1) != '7')) {
                    // Оставляем как есть (уже содержит код страны)
                }
                
                // Добавляем знак + в начало
                return '+' . $phone;
            };
            
            // Приводим телефон к единому формату
            $formattedPhone = $formatPhone($phone);
            
            // Обновляем телефон в данных заказа
            if ($formattedPhone !== $phone) {
                $data['phone'] = $formattedPhone;
                $this->order->set($data);
                $phone = $formattedPhone;
            }
            
            // Формируем receiver, если он пустой
            if (empty($receiver)) {
                if (!empty($phone)) {
                    $receiver = preg_replace('/[^0-9]/', '', $phone);
                } elseif (!empty($email)) {
                    $receiver = substr($email, 0, strpos($email, '@'));
                } else {
                    $receiver = uniqid('user_', false);
                }
            }
            
            // Формируем email, если он пустой
            if (empty($email)) {
                if (!empty($phone)) {
                    $cleanPhone = preg_replace('/[^0-9]/', '', $phone);
                    $email = 'user_' . $cleanPhone . '@' . $this->modx->getOption('http_host');
                } else {
                    $email = $receiver . '@' . $this->modx->getOption('http_host');
                }
            }

            // Если пользователь авторизован
            if ($this->modx->user->isAuthenticated()) {
                $profile = $this->modx->user->Profile;
                
                if (!$profile->get('email')) {
                    $profile->set('email', $email);
                }
                
                if (!empty($phone) && $profile->get('mobilephone') != $phone) {
                    $profile->set('mobilephone', $phone);
                }
                
                if (!empty($receiver) && $profile->get('fullname') != $receiver) {
                    $profile->set('fullname', $receiver);
                }
                
                $profile->save();
                $customer = $this->modx->user;
                
            } else {
                // Поиск существующего пользователя
                $c = $this->modx->newQuery('modUser');
                $c->leftJoin('modUserProfile', 'Profile');
                
                $filter = [];
                
                if (!empty($phone)) {
                    $filter['modUser.username'] = $phone;
                    $filter['OR:Profile.mobilephone:='] = $phone;
                }
                
                if (!empty($email)) {
                    $filter['OR:Profile.email:='] = $email;
                }
                
                $c->where($filter);
                $c->select('modUser.id');
                
                // Пытаемся найти пользователя
                if (!$customer = $this->modx->getObject('modUser', $c)) {
                    // Создаем нового пользователя
                    $userData = [
                        'username' => !empty($phone) ? $phone : $email,
                        'password' => md5(rand()),
                        'active' => 1
                    ];
                    
                    $customer = $this->modx->newObject('modUser', $userData);
                    
                    $profileData = [
                        'fullname' => $receiver,
                    ];
                    
                    if (!empty($email)) {
                        $profileData['email'] = $email;
                    }
                    
                    if (!empty($phone)) {
                        $profileData['mobilephone'] = $phone;
                    }
                    
                    $profile = $this->modx->newObject('modUserProfile', $profileData);
                    $customer->addOne($profile);
                    
                    // Добавляем настройку языка
                    $setting = $this->modx->newObject('modUserSetting');
                    $setting->fromArray([
                        'key' => 'cultureKey',
                        'value' => $this->modx->getOption('cultureKey', null, 'en', true),
                    ], '', true);
                    $customer->addMany($setting);
                    
                    if (!$customer->save()) {
                        $customer = null;
                    } elseif ($groups = $this->modx->getOption('ms2_order_user_groups', null, false)) {
                        $groupRoles = array_map('trim', explode(',', $groups));
                        foreach ($groupRoles as $groupRole) {
                            $groupRole = explode(':', $groupRole);
                            $roleId = null;
                            if (count($groupRole) > 1 && !empty($groupRole[1])) {
                                $roleId = is_numeric($groupRole[1]) ? (int)$groupRole[1] : $groupRole[1];
                            }
                            $customer->joinGroup($groupRole[0], $roleId);
                        }
                    }
                } else {
                    // Пользователь найден - обновляем данные
                    $profile = $customer->getOne('Profile');
                    if ($profile) {
                        $changed = false;
                        
                        if (!empty($phone) && $profile->get('mobilephone') != $phone) {
                            $profile->set('mobilephone', $phone);
                            $changed = true;
                        }
                        
                        if (!empty($email) && $profile->get('email') != $email) {
                            $profile->set('email', $email);
                            $changed = true;
                        }
                        
                        if (!empty($receiver) && $profile->get('fullname') != $receiver) {
                            $profile->set('fullname', $receiver);
                            $changed = true;
                        }
                        
                        if ($changed) {
                            $profile->save();
                        }
                    }
                }
            }
        }

        $response = $this->invokeEvent('msOnGetOrderCustomer', [
            'order' => $this->order,
            'customer' => $customer,
        ]);
        if (!$response['success']) {
            return $response['message'];
        }

        return $customer instanceof modUser ? $customer->get('id') : 0;
    }
        
}

согласно священописанию в консоле делаю так:
<?php
if ($miniShop2 = $modx->getService('miniShop2')) {
  $miniShop2->addService('order', 'my_OrderHandler',
      '{core_path}components/minishop2/custom/order/my_msorderhandler.class.php');
}
Пробую, и ничего не меняется. На пару с ИИ добрел до системной настройки, с ключем ms2_order_handler_class и там указал свой класс. Перестало работать вообще. Т.е. тыкаю на кнопку «сделать заказ» на самом сайте и ничего не происходит.
Из чего делаю вывод, что класс мой не зарегистрировался.

Дальше меняю настройку ms2_services.
она у меня выглядела так:
{«cart»:[],«order»:[«my_OrderHandler»],«payment»:[],«delivery»:{«mydelivery»:"{core_path}components\/minishop2\/custom\/delivery\/my_msdeliveryhandler.class.php"}}

т.к. я уже ранее подрубал собственную службу доставки, и она вроде как исправно работает, делаю по образу и подобию с order, хотя ИИ визжит, что так делать нельзя, и у этой настройки должно быть только название класса.

В логах живет вот такая ошибка:

(ERROR @ /home/c/cz42644/test-iflower/public_html/core/components/minishop2/model/minishop2/minishop2.class.php: 484) [miniShop2] Could not load custom class at "/home/c/cz42644/test-iflower/public_html/my_OrderHandler"
Т.е. я так понимаю, он ищет файл с моей службой почему-то не так где надо, по сути в корне. И как ему указать, где искать — не ведаю.

Вообщем, итог такой, что либо ничего не меняется, либо не работает вовсе.

Что и где я делаю не так?
Артур Шевченко
20 февраля 2026, 19:08
0
Вот тебе моё мнение, через полгода-год заказчикам будем всё равно на чём ты будешь делать сайт, гораздо больше их будет волновать вопрос: умеешь ли ты пользоваться ИИ-агентам? Именно ИИ позволяет ускорится в два-три раза и твой стэк уже не имеет значение, важно будет только умение решать бизнес-задачи и ставить задачи ИИ-агенту. Так что рекомендую начинать осваивать именно эти технологии.
Артур Шевченко
20 февраля 2026, 18:45
0
minishop3 недавно вышел, он ещё не прошёл обкатку и без опыта в разработке переезжать, наверное, не стоит. Многое из того, что тебе нужно @Николай Савин уже либо сделал, либо это у него в планах. Поддержать Николая можно донатом.

Отправить на карту СберБанка messenger.online.sberbank.ru/sl/kPLh3bewMs93eW9Hl
Отправить на карту Тинькофф www.tinkoff.ru/sl/2V9U9RrcJZP
Отправить на YooMoney yoomoney.ru/fundraise/RPkkYwNcL7A.230131
QIWI к сожалению недоступен до восстановления их банковской лицензии
Казахстан Каспи по номеру +7 701 282 77 37
Если Вы находитесь в Казахстане и хотите сделать пожертвование на счет ИП, можем сделать официальные документы (при условии адекватной суммы).

Крипта
USDT TRON (TRC20) TU3gzTp2Rt3wPcts1xiXtwWiu7riC8s56q
Bitcoin — BTC 1LxpXEBBCEQYoswu8tGo6TEU1C8JfmRT18
The Open Network — TON UQAeMteI6GWxyCan_QOXX8sKnDAr5ApF-9FK7f-g2qxVlz-e

Со своей стороны обещаю скорый выпуск интеграции со СДЕК.
Олег Захаров
20 февраля 2026, 16:01
0
Компонент очень нужный и мне кажется будет востребован.
У меня тут задача стоит сделать что-то подобное на сайте на движке на MODX 2.8 — там есть старые другие решения.
Но задумываюсь о глобальном переносе на 3-ю версию.
Олег Захаров
20 февраля 2026, 16:00
0
ну я подумал что возможно ты сам лично уже где-то у себя на заказе рабочем внедрил и есть рабочий сайт
Олег Захаров
20 февраля 2026, 15:58
0
А какой компонент для личного кабинета и авторизации используется?
Андрей
20 февраля 2026, 15:53
+1
вот нашел еще проще решение для текущего пользователя, без id
$profile = $modx->user->getOne('Profile');
return $profile->get('extended')[$input];
и вызов
[[!userField? &input=`tv_name`]]
но все равно хотелось бы понять причины и может есть штатное решение.
Олег Захаров
20 февраля 2026, 14:42
0
тут пришла мысль что никто не захочет просто так делиться своим опытом за бесплатно. Можно было бы сделать статьи и кейсы платными? Типа хочешь прочитать инструкцию или кейс по настройке того или иного компонента — ведь кто-то потратил время на написание инструкции — стоимость 100 руб.
Тут желательно конечно не переусердствовать. Но и обидно не будет тратить время на написание кейсов и инструкций.
А чтобы было понятно что больше всего интересует людей — было бы неплохо сделать список вопросов, на которые нужны ответы — типа голосование или например в описании компонентов добавить голосование за необходимость написания кейсов и готовность оплатить или сбор средств на написание инструкций. Понятно что есть стандартные инструкции, но они не всегда понятные.
И часто бывают брошенные компоненты. Можно было бы собирать средства на его дальнейшее развитие.