Хранить объекты будем в базе данных MODX. Для этого создадим в ней табличку с таким же префиксом, как и у других таблиц:
CREATE TABLE `modx_things_names` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`description` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`active` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,
PRIMARY KEY (`id`),
INDEX (`active`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE utf8_general_ci;Ну и можно через PhpMyAdmin заполнить тестовыми данными

Чтобы MODX мог получать данные из нашей таблицы, ему надо о ней «рассказать». Для этого нужно создать xPDO-модель. Создаём папку /core/components/things/model/things/ и в ней файл metadata.mysql.php
<?php
$xpdo_meta_map = array(
'xPDOSimpleObject' => // Наши объекты будут расширять xPDOSimpleObject
array(
0 => 'ThingsName', // Придумываем название класса для наших объектов
),
);Если мы создаём несколько таблиц в рамках одного дополнения, прописываем все эти таблицы в нашем файле. Теперь для каждой таблицы нужно создать 3 файла:
/core/components/things/model/things/thingsname.class.php
<?php
class ThingsName extends xPDOSimpleObject {}/core/components/things/model/things/mysql/thingsname.class.php
<?php
require_once (dirname(dirname(__FILE__)) . '/thingsname.class.php');
class ThingsName_mysql extends ThingsName {}/core/components/things/model/things/mysql/thingsname.map.inc.php
В этом файле нужно описать все поля объекта и его связи.
<?php
// Указываем, к какому объекту относится описание
$xpdo_meta_map['ThingsName'] = array(
'package' => 'things',
'version' => '1.1',
'table' => 'things_names', // Имя соответствующей таблицы
'extends' => 'xPDOSimpleObject',
'fields' => // Список полей объекта
array(
'name' => '',
'description' => '',
'active' => 1,
),
'fieldMeta' =>
array( // Описываем свойства каждого поля
'name' =>
array(
'dbtype' => 'varchar', // Тип поля в БД
'precision' => '255', // Длина поля
'phptype' => 'string', // Тип поля в PHP
'null' => false, // Допустимо ли значение NULL
'default' => '', // Значение по умолчанию
),
'description' =>
array(
'dbtype' => 'text',
'phptype' => 'string',
'null' => true,
'default' => '',
),
'active' =>
array(
'dbtype' => 'tinyint',
'precision' => '1',
'phptype' => 'boolean',
'null' => true,
'default' => 1,
),
),
);Этого достаточно, чтобы следующий код успешно отработал в любом сниппете:
<?php
$modx->addPackage('things', MODX_CORE_PATH . 'components/things/model/');
$things = $modx->getCollection('ThingsName');
$output = array();
foreach ($things as $thing) {
$output[] = $thing->name;
}
return implode(PHP_EOL, $output);Но нам нужно, чтобы список объектов был получен в процессоре getlist, чтобы вывести потом в табличке.
Можно вызывать метод addPackage в процессоре, но процессоров у нас потом будет несколько, поэтому вызовем этот метод в коннекторе /assets/components/things/connector.php:
<?php
$base_path = dirname(__FILE__);
while (!file_exists($base_path . '/config.core.php')) {
$base_path = dirname($base_path);
}
require_once $base_path . '/config.core.php';
require_once MODX_CORE_PATH . 'config/' . MODX_CONFIG_KEY . '.inc.php';
require_once MODX_CONNECTORS_PATH . 'index.php';
// Подключаем модель наших объектов
$modx->addPackage('things', MODX_CORE_PATH . 'components/things/model/');
$modx->request->handleRequest(array(
'processors_path' => MODX_CORE_PATH . 'components/things/processors/',
'location' => '',
));Теперь в процессоре мы можем получить список всех объектов, подставив свойства limit и start:
<?php
class ThingsGetListProcessor extends modProcessor {
public function process() {
$array = array();
// Создаём запрос
$q = $this->modx->newQuery('ThingsName');
// Узнаём общее количество объектов
$total = $this->modx->getCount('ThingsName', $q);
// Передаём в запрос start и limit
$limit = $this->getProperty('limit');
$start = $this->getProperty('start');
$q->limit($limit, $start);
// Получаем объекты и добавляем их в массив
$objects = $this->modx->getCollection('ThingsName', $q);
foreach ($objects as $object) {
$array[] = $object->toArray();
}
// Отдаём данные в виде массива табличке ExtJS
return json_encode(array(
'success' => true,
'total' => $total,
'results' => $array
));
}
}
return "ThingsGetListProcessor";Как ни удивительно, для таких процессоров в MODX тоже есть заготовки. Всё, что мы прописали здесь (и даже немного больше) уже прописано в классе modObjectGetListProcessor. Мы можем унаследоваться от него, указав только нужный нам класс объекта:
<?php
// Меняем название процессора — просто для удобства
class ThingsNameGetListProcessor extends modObjectGetListProcessor {
public $classKey = 'ThingsName'; // Класс объекта
public $defaultSortField = 'id'; // По какому полю сортировать
}
return "ThingsNameGetListProcessor";В табличке выведем новые поля, которые есть у наших объектов:
Things.grid.Names = function (config) {
config = config || {};
Ext.apply(config, {
columns: [
{dataIndex: 'id', width: 150, header: 'ID'},
{dataIndex: 'name', width: 250, header: 'Name'},
// Добавляем новые колонки
{dataIndex: 'description', width: 500, header: 'Description'},
{dataIndex: 'active', width: 100, header: 'Active'}
],
autoHeight: true,
viewConfig: {
forceFit: true,
scrollOffset: 0
},
url: Things.config.connector_url,
action: 'mgr/thing/getlist',
// Добавляем новые поля
fields: ['id','name', 'description', 'active'],
paging: true,
pageSize: 1
});
Things.grid.Names.superclass.constructor.call(this, config);
}
Ext.extend(Things.grid.Names, MODx.grid.Grid);
Ext.reg('things-grid-names', Things.grid.Names);У колонок можно указать renderer — это функция, которая определяет, как оформить поле в зависимости от его значения:
// ...
{dataIndex: 'active', width: 100, header: 'Active', renderer: function(value) {
if (value) { // Если значение поля == true
return '<span class="green">Yes</span>';
} else { // Иначе
return '<span class="red">No</span>';
}
}}
// ...Так же renderer можно использовать, чтобы отобразить картинку, если в базе хранится её адрес:
// ...
{dataIndex: 'image', width: 100, header: 'Image', renderer: function(value) {
return '<img src="' + value + '">';
}}
// ...На этом работу с табличкой, думаю, закончим. В следующих уроках попробуем разобраться с окнами, чтобы создавать или редактировать наши объекты.
Объектная
При вызове сниппета ничего не происходит, в логах ошибка:
Could not get table class for class: FormconstructorName Error 42000 executing statement: Array ( [0] => 42000 [1] => 1064 [2] => You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS `FormconstructorName`' at line 1 )P.S. ThingsName заменил на FormconstructorNameЕсли интересно, то могу дать доступ в админку.
Вот этот файл thingsname.map.inc.php должен лежать в
а у тебя в статье
/core/components/things/model/things/things/thingsname.map.inc.php
на:
/core/components/things/model/things/mysql/thingsname.map.inc.php
Я часа два сидел и не мог понять, почему у меня не работает))
'description' => array( 'dbtype' => 'text', 'phptype' => 'text', 'null' => true, 'default' => '', ),phptype' => 'text' не существует, есть phptype' => 'string'MODx.grid.Names = function (config) { // Придумываем название, например, «Names» config = config || {}; Ext.apply(config, { // Сюда перемещаем все свойства нашей таблички columns: [ // Перечисляем список столбцов {dataIndex: 'id', width: 150, header: 'ID'}, {dataIndex: 'pagetitle', width: 250, header: 'Товар'}, ], name: 'resource_id', url: MODx.config.connector_url, params: { action: 'resource/getlist', id: 523 }, typeAhead: true, editable: true, anchor: '99%', paging: true, pageSize: 20, fields: ['pagetitle','id'], }); MODx.grid.Names.superclass.constructor.call(this, config); } Ext.extend(MODx.grid.Names, MODx.grid.Grid); Ext.reg('things-grid-names', MODx.grid.Names);Пишет что процессор не найдет. Если вместо params поставить baseParams то выводятся все ресурсы со всех родителей, как будто выставлен родитель = 0. Подскажите как можно в процессор передать значения?