Наверх

Как работают дополнения MODX. Часть 1 — Namespace и Controller

Разберём создание дополнения MODX руками — без всяких заготовок типа modExtra.


Мы будем разбирать создание именно «дополнения», а не «пакета» или «компонента». Для понимания разницы приведу в пример работу со сниппетами в MODX. Мы можем нажать в админке кнопку «Новый сниппет», ввести в открывшейся форме имя Hodor и код:
<?php
return 'Hodor!';
После сохранения мы можем вызывать его в любом месте шаблона и пользоваться сниппетом. Но если мы хотим использовать этот сниппет на нескольких сайтах, можно сделать транспортный пакет, который будет содержать в себе сниппет Hodor.

При разработке дополнений так же сначала нужно понять, как дополнения работают и из чего состоят. И только потом можно задумываться над тем, как же «запаковать» дополнение в транспортный пакет.

Если вы хотите разобраться, что такое «дополнение», как дополнения работают и что сделать, чтобы создать своё дополнение, настоятельно советую создать тестовый сайт на хостинге modhost.pro и повторять все действия, описанные в статье. Сложно будет понять весь механизм, не пройдя «ручками» по всем этапам.

Создадим в корне сайта папку things — это будет папкой нашего дополнения. А чтобы MODX знал, что эта папка вообще существует, создадим «Пространство имён» (в выпадающем списке внутри шестерёнки ilyaut.ru/cloud/1WpAB1.png)

  • Имя things
  • Путь к ядру {base_path}things/

Адреса дополнений MODX выглядят так: /manager/?a={controller}&namespace={namespace}
Мы создали пространство имён things — это namspace. Ну а контроллер можно назвать как угодно. Давайте назовём index — так же, как принято в HTML для главных страниц. Открываем в браузере страницу
/manager/?a=index&namespace=things

Понятное дело, что появилась ошибка — ведь папка у нас пустая. Создадим файл с тем именем, какое мы выбрали для контроллера. Если вы захотите, чтобы у вашего дополнения было несколько страниц, создавайте по одному файлу для каждой нужной страницы и придумывайте имена контроллеров (файлов). Для нашего контроллера имя файла будет таким: index.class.php.

Если MODX не даёт вам создать файл php, просто добавьте расширение php в системную настройку upload_files. Не забудьте по завершении работ удалить его из этого списка!

Когда пустой файл будет создан, страница нашего компонента отвалится с ошибкой 500. Скорее всего текст ошибки вы не увидите из-за настроек сервера. Если так и есть, то просто допишите в начало файла /manager/index.php такую строчку:
ini_set('display_errors', 1);

Теперь, если мы переведём текст ошибки с английского на русский, мы поймём, что
Класс 'ThingsIndexManagerController' не найден...

Дело в том, что в MODX приняты правила названий классов. Для файла контроллера название класса будет таким: {namespace}{controller}ManagerController. Запоминать это необязательно, всегда можно узнать требуемое название класса из текста ошибки.

Идём на поводу у MODX и описываем в нашем файле нужный класс:
<?php
class ThingsIndexManagerController {}

После этого текст ошибки изменится — теперь MODX сообщает, что он пытается вызвать метод setProperties какого-то объекта, который не получен (on null). Пока непонятно. Смотрим код ошибки дальше.

Советую нажать Crtl+U, чтобы увидеть исходный код страницы — там текст ошибки будет разделён на строки. В строке с номером 0 есть имя нашего класса и имя метода getInstance. Вероятно, проблема в том, что у нас такого метода не существует. Давайте, его добавим. По названию метода можно предположить, что он должен «получать экземпляр» (не стесняйтесь пользоваться переводчиком). Экземпляр внутри класса — это $this. Значит, метод будет выглядеть так:
<?php
class ThingsIndexManagerController {
    public function getInstance(){
        return $this;
    }
}

Смотрим, что теперь MODX хочет от нас. А хочет он метод setProperties, а у нас такого нет. Создадим его. У нас пока никаких свойств нет, они нам не нужны, поэтому метод не будет делать ничего.
public function setProperties() {}

Следующий требуемый метод — это initialize. Проведём тот же трюк:
public function initialize() {}

Новая ошибка и новый метод:
public function render() {}

Теперь ошибка уже непохожа на предыдущие. Остановимся и проанализируем последние действия. Мы добавили метод render. Это слово можно перевести как «отобразить». Давайте в коде укажем, что «отобразить» надо строку Hello world:
<?php
class ThingsIndexManagerController {
    public function getInstance(){
        return $this;
    }
    
    public function setProperties() {}
    
    public function initialize() {}
    
    public function render() {
        return 'Hello world';
    }
}

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

Чтобы воспользоваться этой заготовкой и вывести все элементы админки, нужно наш класс унаследовать от класса modExtraManagerController. Пока удалим все наши методы — ведь они уже есть в заготовке:
<?php
class ThingsIndexManagerController extends modExtraManagerController {}

Теперь по адресу нашей странички откроется полнофункциональная страница админки. Чтобы понять, какие возможности предоставляет нам заготовка, можно посмотреть в её код. Загляните, почитайте и переведите хотя бы названия методов: /core/model/modx/modmanagercontroller.class.php.

Меня, например, заинтересовал метод getPageTitle. Давайте, попробуем поменять title страницы нашего дополнения:
<?php
class ThingsIndexManagerController extends modExtraManagerController {
    public function getPageTitle() {
        return 'Things';
    }
}

Кроме того, есть метод getTemplateFile. Ну что ж, давайте создадим файл-шаблон для нашего компонента. В папке things создадим файл home.tpl (если расширение tpl тоже запрещено, вы теперь знаете, что делать):
<h2>Things</h2>

И укажем путь к этому файлу в методе getTemplateFile:
<?php
class ThingsIndexManagerController extends modExtraManagerController {
    public function getPageTitle() {
        return 'Things';
    }
    public function getTemplateFile() {
        return dirname(__FILE__) . '/home.tpl';
    }
}

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

Заходим в раздел «Меню» и создаём пункт в нужном месте (например, внутри пункта «Приложения»):


И вот, у нас готово наше собственное дополнение


На странице дополнения вы можете подключить, например, jQuery и Bootstrap и вывести пользователю какую-нибудь интерактивную информацию.

Но вообще, в MODX не принято баловаться сторонними фреймворками, так как в комплекте с MODX уже идёт замечательный фреймворк ExtJS, который заменяет сразу и jQuery, и Bootstrap.

В следующей статье мы приведём наше дополнение в стандартный для MODX вид с использованием ExtJS.


21 комментарий

  1. Саня 22 октября 2017, 19:40 # +2
    Очень круто. Спасибо
    1. Павел Александрович Устюгов 22 октября 2017, 23:23 # +2
      Илья! Респект тебе навсегда! Ждём продолжения темы, ты выбрал самое актуальное направление для написания статей.
      1. Denis Efremov 23 октября 2017, 02:15(Комментарий был изменён) # -2
        ExtJS — замечательный, тут спору нет, но последняя его версия. Так как, сейчас уже давно есть бесплатные фреймворки для создания реактивных пользовательских интерфейсов, гораздо более высокого качества и внешнего вида кода, которые исключают DOM-Traversing из процесса разработки, в принципе. Плюс ко всему, бутстрап — решает вопрос мобильной версии на 80%. А как его решает ExtJS?

        Если MODX не даёт вам создать файл php, просто добавьте расширение php в системную настройку upload_files.
        Это точно безопасно?

        Вам не кажется, что все это как-то сложно, для простого создания расширения? Я использую другую CMS и там есть 5 типов аддонов, которые создаются одной командой в консоли, причем она сама определяет из названия, какой тип аддона необходимо создать.
        1. Илья Уткин 23 октября 2017, 07:23 # +1
          Нет, статья написана как раз с цель показать, насколько всё сложно в MODX. Чтобы предостеречь начинающих разработчиков — не связывайтесь с MODX ни в коем случае. Вот вы про какую CMS говорите? Может, мне на неё перейти?
          1. Denis Efremov 23 октября 2017, 07:35 # 0
            Илья, по-моему, вы меня троллите…

            Может вам лучше посмотреть на github?
            1. Denis Efremov 23 октября 2017, 07:39(Комментарий был изменён) # 0
              Я был бы очень рад видеть вас среди нас, и взаимодейстовать с вами в разработке. И я вас не тролю, а говорю абсолютно серьезно.

              github.com/piterden
              1. Илья Уткин 23 октября 2017, 08:38 # 0
                Но ваш комментарий очень похож на троллинг. Пришли в статью, где описывается как создать дополнение для MODX (а я уверен, есть люди, которым хочется это узнать) и пытаетесь описать минусы MODX.

                Для обсуждения плюсов/минусов MODX есть другие статьи:

                Я стараюсь в таких обсуждениях не участвовать, потому что ни разу не видел, чтобы кто-то кого-то убедил перейти с одной CMS на другую в комментариях в интернете.
                1. Denis Efremov 23 октября 2017, 15:04(Комментарий был изменён) # 0
                  Вы меня извиниите, но я вас не убеждаю.
                  На мой вопрос по-существу, вы не ответили!

                  Также, у меня нету желания, обсуждать плюсы и минусы Modx. Уверен — вам не выстоять в подобной полемике. Я лишь отметил очевидные диссонансы вашей статьи.

                  Однако, на Modx свет клином не сошелся. И я хочу чтобы другие разработчики были в курсе кое-каких ньюансов, о которых вы умалчиваете, например:

                  • Что нету ничего замечательного, в устаревшем, не только морально, но и физически, ExtJS v3.4.
                  • Что добавление расширения php в системную настройку upload_files, может закончиться плачевно.
                  • Что jQuery уже давно стараются не использовать.
                  • Что есть CMS, у которых весь процесс, описанный в вашей статье — занимает одну команду в консоли.

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

                  Илья, извините меня, пожалуйста. Ничего личного…
                  1. Илья Уткин 23 октября 2017, 15:24 # 0
                    Ок, отвечу по существу:

                    1. Да, ExtJS устарел, ужасен на мобильных устройствах.
                    2. Добавить расширение php к разрешённым нужно только в обучающих целях. Статью дополнил, добавил напоминание о необходимости вернуть как было. За это спасибо.
                    3. jQuery я упомянул только для понимания того, что разработчик волен делать всё, что он захочет.
                    4. В MODX создание дополнения тоже автоматизировано, причём существует несколько разных скриптов — выбирай наиболее удобный. В статье я рассказываю, как дополнения вообще работают, из чего состоят.

                    По поводу PyroCMS — это хорошо, что в ней нет некоторых минусов MODX. Но вы же не будете утверждать, что PyroCMS — идеал? Если вы уж против умалчивания, расскажите честно о минусах PyroCMS. Напишите, кому она не подойдёт, чтобы люди не теряли времени.
                    1. Denis Efremov 23 октября 2017, 15:44 # 0
                      Минусы описаны здесь:
                      github.com/pyrocms/pyrocms/issues
            2. УстюПаша 01 ноября 2017, 11:34 # +1
              посмотрел ПироCMS. Порадовало, что она быстрая и базуриется на Laravel. В то же время скажу, что modx приятен людям, не имеющим больших навыков разработки. На modx легко делать сайты без самого программирования. Можно использовать огромную базу уже разработанных дополнений под ecommerce и создание интернет магазина будет лишь сводиться к интеграции вёрстки в cms используя несложный синтаксис.

              Про Pyro — документация на английском. Ее мало. Мало готовых дополнений. Не нашел я живого сообщества, как по modx. И на биржах фриланса полно заказов по modx, но по pyro я тоже не нашел. Через пару лет — может быть…
              1. Denis Efremov 01 ноября 2017, 13:48 # 0
                Я и сам, раньше использовал Modx, однако, мне пришлось, как то раз, делать сайт-конкурс, где люди должны добавлять контент и должно проводиться голосование.

                Нет — сайт работал, я ничего не хочу сказать.

                Modx не имеет очень важного — генераторов CRUD, без которых, дальше сайтов-визиток становится трудно и долго.

                В Пиро высокий порог входа, и с доками вообще беда. Впрочем, с тестами тоже… Но зато там код категории A на codacy, что по сути — означает отсутствие необходимости в документации, ввиду комментированности и строгой структуры кода, а также, жесткой зависимости от названий.

                В целом — это фреймворк для написания дополнений, реализованный, с применением многих принципов предметно-ориентированного проектирования, с использованием многих «модных» )) паттернов проектирования, а также, имеющий дополнительный абстрактный слой между пользователем и ORM (нормальным Eloquent ORM, а не как у modx — который даже union не делает). Этот слой, храня данные обо всей остальной структуре базы, в нескольких таблицах, динамически меняет структуру БД, проводя микро-миграции Laravel, по событиям Eloquent ORM (изменениям в данных сервисных таблиц слоя). То есть это виртуальный NoSQL на базе реляционной БД.

                Про метакод и систему аддонов можно еще по стольку же рассказывать…

                По поводу сообщества — вы, абсолютно не правы. Есть чат в слаке и форум. Бесплатный курс английского — это бонусная фича, только для тех, кто его не знает))

                Вам лично, я могу оказать поддержку на русском (я могу материться — имейте ввиду) )))

                Подводя итог, скажу, что я не позиционирую Пиро, как хорошее начало карьеры разработчика. Скорее, ЦА Пиро, это те разроботчики, которым становится уже маловато Modx, и которые вместе с этим, готовы развиваться.

                Я, искренне убежден, что подход, предложенный мне этой ЦМС, близок к правильному.

                PS Кстати, Twig — ничуть не сложнее и в разы функциональнее недошаблонизатора без-названия (это же беглое АПИ для смарти???), а Пиро пробрасывает весь Eloquent прямо в Twig. Вдумайтесь. Там union прямо в Twig работает.
                1. УстюПаша 01 ноября 2017, 14:27 # +1
                  спасибо за развернутый ответ. в модх тоже шаблонизатор неплохой есть Fenom.
            3. Василий Столейков 30 октября 2017, 09:48 # +1
              Спасибо за последовательный разбор каждой ошибки. Так лучше понимаешь структуру дополнения!
              1. Александр Шинкарь 08 ноября 2017, 09:21 # 0
                Илья здравствуйте.
                Как вы отнесетесь к тому если сниму видео урок по вашему циклу уроков по созданию дополнения?
                1. Илья Уткин 08 ноября 2017, 13:21 # 0
                  Отношусь положительно, даже ссылку на этот видеоурок у себя на сайте размещу =)
                  1. Евгений Батулин 10 июня 2018, 17:00 # 0
                    Александр здравствуйте! Вы сняли задуманный урок по созданию дополнений?
                  2. Евгений Батулин 10 июня 2018, 18:48 # 0
                    Илья здравствуйте! Прошу вас помочь мне. Создал в корне папку things, в ней файл пробовал и index.php и index.class.php, но при вводе в адресную строку site_name/manager/?a=index&namespace=things появляется ошибка Could not find action file at: index.php Подскажите пожалуйста в чем проблема. Спасибо
                    1. kimoncar 24 июня 2018, 21:28 # 0
                      Аналогичная ошибка. Получилось решить проблему?
                      1. kimoncar 24 июня 2018, 21:37 # 0
                        Невнимательность моя — вот ошибка! В имя пространства имен попал «слэш» (/), удалил и заработало
                    2. Николай Савин 16 сентября 2018, 14:49 # 0
                      Зашел специально чтобы сказать спасибо. Статья очень полезная, правильная и нужная! И что самое главное аналогов нет!

                      Авторизация

                      через сервис Loginza:


                      Шаблоны MODX

                      1 2 Дальше »

                      Объектная
                      модель
                      MODX