Jump to main content Jump to doc navigation

Здесь мы совершаем переход от автономного Ext JS к MODX. Многие вещи одинаковы, но, к сожалению, кривая обучения все еще растет. Нашей первой будет как можно более простая задача: мы собираемся создать страницу настраиваемого менеджера, в которой перечислены типы контента. Да, это то, что MODX уже делает в Система -> Типы содержимого, но в этом суть: мы хотим попробовать свои силы в воссоздании того, что MODX уже предоставляет.

Вот скриншот встроенной сетки, отображающей типы контента. Вот что мы собираемся воссоздать в нашем собственном CMP:

Ориентируя себя

Предыдущие уроки здесь были просты в том смысле, что они ставили все перед вами: вы должны были включить файлы JavaScript и CSS Ext JS, но помимо этого, это был просто вопрос манипулирования JavaScript. Однако, как только мы перейдем к менеджеру MODX, все может стать более сложным. Вещи немного скрыты в различных папках и файлах классов PHP. А также у нас есть дополнительная проблема, связанная с разрешениями пользователей. Итак, давайте сделаем глубокий вдох и рассмотрим, что мы видим внутри менеджера.

Менеджер

Менеджер MODX действует как автономное приложение. Большинство файлов, с которыми мы будем иметь дело, находятся в следующих местах:

  • manager/assets/modext: дом для различных конфигураций Ext JS, панелей, виджетов и т. д.
  • manager/controllers/: дом для PHP кода, который загружает Ext JS вещи. JS указывает на коннектор.
  • connectors/: К счастью, это гнездо файлов исчезает в MODX 2.3, но в MODX 2.2 и ранее коннекторы просто указывают на процессор.
  • core/model/modx/processors/: обрабатывает выборку данных
  • core/model/modx/modmanagerrequest.class.php : отвечает за обработку всех запросов в менеджере
  • core/model/modx/modprocessor.class.php : отвечает за фактическое получение данных.

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

Ну, держитесь! Поскольку контроллеры менеджера MODX добавляют дополнительный уровень сложности, и они плохо документированы, я собираюсь пропустить их для этой демонстрации.

Контроллер Ajax

Ваши контроллеры Ajax должны быть доступны через HTTP, поэтому их типичное расположение будет внутри папки assets/, а точнее, где-то внутри assets/components/<your_pkg>/.

<?php
/**
 * Контроллер для запросов Ajax.
 */
// Отрегулировать путь соответственно
$docroot = dirname(dirname(dirname(dirname(__FILE__))));
include $docroot . '/config.core.php';
if (!defined('MODX_API_MODE')) {
    define('MODX_API_MODE', false);
}
include_once MODX_CORE_PATH . 'model/modx/modx.class.php';

$modx = new modX();
$modx->initialize('mgr');

if (!$modx->hasPermission('view_document')) {
    header('HTTP/1.0 401 Unauthorized');
    print 'Операция не разрешена.';
    exit;
}
// Следующие значения стандартны для Ajax URL в Ext JS
$start = (int) $modx->getOption('start',$_POST,0);
$limit = (int) $modx->getOption('limit',$_POST,20);
$sort = $modx->getOption('sort',$_POST);
$dir = $modx->getOption('dir',$_POST,'ASC');

// error_log(print_r($_POST,true));  // <--- раскомментируйте эту строку для отладки

$c = $modx->newQuery('modResource');
$count = $modx->getCount('modResource',$c);
$c->sortby($sort,$dir);
$c->limit($limit,$start);

//$c->prepare(); error_log($c->toSQL()); // <-- раскомментируйте эту строку для отладки

$pages = $modx->getCollection('modResource',$c);

$list = array();
foreach ($pages as $p) {
    $array = $p->toArray();
    $list[] = $array;
}

// Формат вывода недостаточно хорошо документирован, однако он требует узел для "total" and "rows"
print '{"total":"'.$count.'","results":'.$modx->toJSON($list).',"success":true,"msg":"Got our rows..."}';

//error_log(print_r($list,true));  // <-- еще одна точка отладки

@session_write_close();
exit();

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

Преимущества простых контроллеров

  1. Вы можете отладить вывод, посетив страницу напрямую, например, http://yoursite.com/assets/components/your_pkg/my_ajax_controller.php - вы должны увидеть данные JSON или, возможно, некоторые ошибки PHP.
  2. Проверка прав доступа проста, просто обновите $modx->hasPermission('permission_key_here')
  3. Никакой дополнительной документации или сложности не требуется

Недостатки в том, что это не «официальный» способ (не знаю, где задокументирован «официальный» способ), поэтому вы не сможете воспользоваться маршрутизацией менеджера, а если вы захотите переопределить поведение собственного контроллера через тему менеджера MODX, вы не сможете это сделать, т.к. эта штука жестко запрограммирована. Поскольку этот способ намного проще, а другой не документирован, я считаю, что это достойный компромисс.

Ваш CMP

Следующий код вы можете вставить в вашу директорию core/components/<your_pkg_name/ и ссылаться на нее как на действие при создании CMP.

<?php
/**
 * Обычный MODX CMP
 */
$url = MODX_ASSETS_URL.'components/your_pkg_name/'; // <-- update this
//------------------------------------------------------------------------------
//!Grid
//------------------------------------------------------------------------------
$modx->regClientStartupHTMLBlock("<script>
function myactions(val) {
    return '<a href=\"index.php?a=30&id='+val+'\">Edit</a>';
}


Ext.onReady(function(){

    // Создать хранилище данных
    var store = new Ext.data.JsonStore({
        root: 'results',
        totalProperty: 'total',
        idProperty: 'id',
        remoteSort: true,

        fields: [
            'id',
            'createdon',
            'pagetitle',
            'action'
        ],

        // Загрузить, используя теги скрипта для кросс-доменного запроса; если данные находятся в том же домене, как
        // данная страница, то использовать HttpProxy было бы лучше
        proxy: new Ext.data.HttpProxy({
            url: '{$url}getpages.php'  // <------- Установите этот параметр с указанием на ваш контроллер Ajax
        })
    });
    store.setDefaultSort('id', 'ASC');


    var grid = new Ext.grid.GridPanel({
        id: 'articlesGrid',
        width:700,
        height:500,
        store: store,
        trackMouseOver:true,  // Подсветит строки при наведении курсора мыши
        disableSelection:true, // Позволит вам выбрать строку(и)
        loadMask: true,  // Сгенерирует крутящуюся иконку

        // Колонки сетки
        columns:[{
            header: 'Дата',
            dataIndex: 'createdon',
            width: 150,
            sortable: true
        },{
            header: 'Заголовок страницы',
            dataIndex: 'pagetitle',
            width: 350,
            sortable: true
        },{
            header: '',
            dataIndex: 'id',
            width: 100,
            sortable: false,
            renderer : myactions,
        }],

        // Панель постраничного разбиения внизу
        bbar: new Ext.PagingToolbar({
            pageSize: 25,
            store: store,
            displayInfo: true,
            displayMsg: 'Отображаются записи {0} - {1} из {2}',
            emptyMsg: "Нет записей для отображения"
        })
    });

    // Отобразить сетку
    grid.render('articles-grid');

    // Запустить загрузку локального хранилища
    // ПРИМЕЧАНИЕ: имена параметров здесь соответствуют ключам в массиве $_POST
    store.load({params:{start:0, limit:25}});
});
</script>");

// Удостоверьтесь, что у вас в HTML добавлен тот же самый элемент div, который указан в методе grid.render()
return '
<h2>Пример</h2>
<div id="articles-grid"></div>';

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

Обычно генерация JavaScript посредством PHP не очень хорошая идея - это то, что обычно осуждается, но это требуется в определенных точках интеграции. «Более правильный» способ сделать это - напечатать некоторые детали конфигурации в виде объектов JavaScript, а затем сослаться на переменные JavaScript в вашем коде. Мы продемонстрируем это позже - сейчас просто попробуйте обдумать, что происходит в коде.

Support the team building MODX with a monthly donation.

The budget raised through OpenCollective is transparent, including payouts, and any contributor can apply to be paid for their work on MODX.

Backers

  • modmore
  • STERC
  • Digital Penguin
  • Jens Wittmann – Gestaltung & Entwicklung
  • Fabian Christen
  • Dannevang Digital
  • Sepia River Studios
  • CrewMark
  • Chris Fickling
  • deJaya
  • eydolan
  • Lefthandmedia
  • Murray Wood
  • Following Sea
  • Anton Tarasov
  • Stéphane Jäggi
  • Raffy
  • Snow Creative
  • A. Moreno
  • Nick Clark
  • JT Skaggs
  • Helen
  • YJ
  • krisznet
  • Richard
  • Yanni

Budget

$306 per month—let's make that $500!

Learn more