Расширение любых таблиц MODX
В очередной раз понадобилось изменить таблицу сайта, менять которую не предусмотрено.
Что обычно люди делают в таких случаях? Верно, редактируют ядро или нужный компонент, и больше их не обновляют. Но ведь это неправильно, и можно решить вопрос иначе.
Пишем обычный плагин, выставляем для него событие OnMODXInit и меняем модель для нужных классов системы или дополнений. Например, я добавил id менеджера в заказ miniShop2:
Больше никаких проблем с обновлениями.
В комментариях возникли вопросы, а что со скоростью?
Отвечаю, этот код отрабатывает примерно за 0.00048 сек. Прикиньте, сколько нужно инициализировать новых классов и добавить полей, чтобы заметить тормоза.
Что обычно люди делают в таких случаях? Верно, редактируют ядро или нужный компонент, и больше их не обновляют. Но ведь это неправильно, и можно решить вопрос иначе.
Пишем обычный плагин, выставляем для него событие OnMODXInit и меняем модель для нужных классов системы или дополнений. Например, я добавил id менеджера в заказ miniShop2:
<?php
switch ($modx->event->name) {
case 'OnMODXInit':
$modx->loadClass('msOrder');
$modx->map['msOrder']['fields']['manager_id'] = 0;
$modx->map['msOrder']['fieldMeta']['manager_id'] = array(
'dbtype' => 'int',
'precision' => 10,
'attributes' => 'unsigned',
'phptype' => 'integer',
'null' => true,
'default' => 0,
);
break;
}Остаётся только физически добавить свои колонки в таблицы базу данных, и MODX работает с ними, как с родными. Сохраняет, выбирает, фильтрует — всё как положено.Больше никаких проблем с обновлениями.
В комментариях возникли вопросы, а что со скоростью?
Отвечаю, этот код отрабатывает примерно за 0.00048 сек. Прикиньте, сколько нужно инициализировать новых классов и добавить полей, чтобы заметить тормоза.
Комментарии: 60
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
И что твоим способом можно обойтись без создания своих компонентов ради моделей, как описано в той инструкции от Николая?
На инновацию не претендую, может я опять изобрёл велосипед.
Fi1osofFi1osofЕсли плагин отключить, то, как-бы, ничего и не расширялось.
Нет, не будет.
Просто мне всегда казалось, что плагины это не самое лучшее решение для многих задач.
Это просто PHP скрипт, который вызывается из другого PHP скрипта. В частности OnMODXInit вызывается из основного класса MODX в момент инициализации контекста.
А на практике в системе и так уже грузятся десятки классов и всё это занимает миллисекунды. Те же классы miniShop2 тоже грузятся, но чуть позже, поэтому нужно вызвать loadClass здесь вручную.
Работа с массивом вообще, считай, ничего не стоит.
Я не могу придумать, как можно по-настоящему затормозить систему таким плагином. Добавить 10 000 полей, разве что, и то не факт.
У меня этот код отрабатывает за 0.00048 сек. Добавил в заметку.
На первый взгляд это попроще будет чем плагины писать
Только плагины miniShop2 позволяют еще и в саму админку всякое добавлять.
Fi1osofОбойти это Вы можете следующим способом:
1. Сделать расширяющий класс
2. Сделать копию необходимых сниппетом от Tickets
3. В копиях сниппетов изменить способ инициализации основного сервиса, чтобы подгружался расширенный класс.
Если воспользуетесь поиском, найдете подробную статью Василия с описанием этого метода.
Вот код плагина:
Вот колонка в базе:
Никто не сталкивался с этим, в чём может быть проблема?
Дословно:
причём если отключить плагин, то этой записи уже не будет. А в логах пусто…
1. Создал плагин точь-в-точь как в этом посте. Повесил на событие OnMODXInit.
2. Добавил в таблицу modx_ms2_orders столбец manager_id joxi.ru/52azjXgu4goPyA
3. В стандартном сниппете msOrder добавил Ни на что не ругается, заказ создается, но в базу записывается 0 всегда. Каким образом сохранять значение в этот столбец?
Вот готовый и рабочий вариант:
Я не могу…
Я бы еще не заполнял к нему описание. Мало ли дело было в нём…
Добавил на всякий случай еще одно событие. Сейчас все работает:
Хотя в консоли класс этот видит.
У меня создано именно такое поле в таблице заказов, и я прямо из заказа отправляю номер менеджера, но в таблицу всегда попадает ноль.
Добавил в таблицу site_content поле import_cid и во внешнем скрипте (modx проинициализирован) пытаюсь получить объект через getObject с условием по этому полю, но выдаёт «Unknown column 'modResource.import_сid' in 'where clause'».
var_dump($modx->map['modResource']); в моём скрипте говорит, что import_сid есть.
Не подскажите в какую сторону копать?
Например добавил столбец content2 в БД и поставил плагин:
<?php switch ($modx->event->name) { case 'OnMODXInit': $modx->map['modResource']['fields']['content2'] = 0; $modx->map['modResource']['fieldMeta']['content2'] = array( 'dbtype' => 'mediumtext', 'phptype' => 'string', 'index' => 'fulltext', 'indexgrp' => 'content_ft_idx' ); break; }Ничего нигде не поменялось. Нужны еще какие-то манипуляции для добавление полей в форму редактирования ресурса?В форму редактирования нужно добавлять самостоятельно.
Если ты что то новое добавляешь в карту объекта и базу данных (уточню на всякий случай что еще и таблицу базы данных нужно расширять ручками) — то так же ручками нужно добавлять новый дополнительный код в js массив полей.
Обычно делают отдельный плагин, чтобы не вносить правки в исходный код MODX.
Вот пример, прямо из рабочего проекта дернул
switch ($modx->event->name){ case 'OnDocFormPrerender': $modx->controller->addHtml(" <script type='text/javascript'> Ext.ComponentMgr.onAvailable('modx-panel-resource', function(){ if(this.items[1].items[0].id == 'minishop2-product-tab'){ var leftCol = this.items[1].items[0].items[0].items[0].items[0].items[0].items[0].items[0]; }else{ if(this.items[1].items[0].id== 'modx-resource-settings'){ var leftCol = this.items[1].items[0].items[0].items[0]; } if(this.items[1].items[1].id == 'modx-resource-settings'){ var leftCol = this.items[1].items[1].items[0].items[0]; } } var kz_title = { anchor: '100%', description: '<b>[[*kz_title]]</br>Заголовок на казахском</b>', fieldLabel: 'Заголовок на казахском', id: 'modx-resource-kz-title', maxLength:255, msgTarget: 'under', name:'kz_title', xtype:'textfield' } leftCol.items.splice(2, 0, kz_title); var kz_description = { anchor: '100%', description: '<b>[[*kz_description]]</br>Описание на казахском</b>', fieldLabel: 'Описание на казахском', id: 'modx-resource-kz-description', maxLength:255, msgTarget: 'under', name:'kz_description', xtype:'textarea' } leftCol.items.splice(4, 0, kz_description); }); </script>"); break; }На выходе получилось вот так prntscr.com/mnm25mА я добавил TV поле и при его сохранении плагин записывал значение в БД
case 'OnDocFormSave': $resource->set('content2', $resource->getTVValue('content2')); $resource->save(); break;Правда, я ожидал, что можно будет делать обычный вызов на странице документа , но он почему-то возвращает массив Надо попробовать твой вариант!Что касается проблемы — смотри, у тебя одновременно есть и поле content2 в таблице ресурсов и такой же TV. Конфликт явный. Надо tv переименовать.
Свои поля в интерфейсе редактирования ресурса MODx
Свои вкладки и поля ресурса в админке MODx