mmxApp - разработка новых composer дополнений

19 апреля в Белграде прошла встреча разработчиков, на которой я рассказал про создание новых composer-only дополнений.



По старой традиции, заодно предложил и готовое решение для этой разработки, как уже было с modExtra и App.

Новый проект называется mmxApp, и предназначен для локальной разработки в Docker на Linux и MacOS.

Давайте посмотрим небольшую демонстрацию:



Что происходит на этом видео?
  1. Клонируем проект из репозитория
  2. Создаём файл с настройками
  3. Переименовываем проект из mmx-app в mega-ultra-app
  4. Запускаем контейнеры Docker
  5. Устанавливаем MODX внутрь контейнера PHP
  6. Заодно ставится и наше новое дополнение
Теперь можно начинать разработку.

Логика работы


Используется 4 контейнера Docker:
MariaDB для базы данных.
Node для фронтеда.
Php-Fpm для бэкенда.
Nginx для вывода этого всего у вас в браузере.

Новое приложение лежит в корне проекта под указанным именем mega-ultra-app. При старте Node и PHP контейнеров, оно монтируется им в корень файловой системы.

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

Но это только исходники, нужно же создать дополнение внутри MODX: пространство имён, плагины, чанки, и всё такое. Для этого используются встроенные CLI скрипты установки и удаления — там нет ничего сложного, просто работа с базой данных.

На мой вгляд, это сильно проще сборки старого транспортного пакета.

Фронтенд


Фронтенд работает с теми же исходниками, но внутри своего Node контейнера.

Я предлагаю использовать Vite вместе с Vue 3 и Bootstrap 5, что даёт нам возможность подключать фронтенд в режиме для разработки с горячей заменой модулей (HMR). В принципе, ничего не мешает использовать React вместо Vue, или любой другой фреймворк.

Для унификации своих дополнений я уже выпустил готовую Vue библиотеку с интеграцией в админку MODX @vesp/mmx-frontend. Просто устанавливаете как зависимость, затем берёте её конфиг и расширяете. mmxForms уже так и делает.

Плагин


Плагин является просто ссылкой на метод handleEvent внутри основного класса App и по умолчанию нужен для двух операций:

  1. Вывод страницы дополнения в админке, путём подмены контроллера на лету с регистрацией js и css.
  2. Обработка запросов в API от админки и, если нужно, публичного сайта.
Скрипты фронтенда могут регистрироваться в двух режимах: разработка и продакшн. Логика такая: если в директории assets/dist дополнения лежит файлик manifest.json со ссылками на собранные файлы, то используем их — это продакшн.

Если такого файла нет, то пробуем подключиться к порту 9090 контейнера Node, для загрузки файлов сервера разработки Vite.

Таким образом, можно при разработке иногда собирать фронтенд для проверки разрмера файлов и скорости загрузки продакшен версии. А потом удалять manifest.json и снова работать с HMR.

Бэкенд


Серверная часть основана на моей библиотеке vesp/core, и основная логика находится в App->run():
  1. Запрос прилетает на адрес, совпадающий с namespace вашего дополнения, например /mega-ultra-app/....
  2. Выставляются маршруты в методе setRoutes().
  3. Если запрос соответствует маршруту, запускается соответствующий контроллер.
  4. В ответ отдаётся JSON, с которым и работает Vue приложение.
Контроллеры должны быть наследниками Vesp\Controllers\Controller. Для работы с таблицами исользуются модели Eloquent.

В mmxApp лежит пример работы с таблицей items: миграция, модель и контроллер — так что можно надобавлять всего по образу и подобию, наделать маршрутов и организовать работу с любыми сущностями.

Сниппеты и Чанки


У меня сниппет ссылается на метод App->handleSnippet(), по той же логике, что и плагин. Подключает js и css в нужном режиме и в качестве ответа выводит только элемент для монтирования фронтенд приложения.

Понятное дело, что это просто пример, использовать Vue на публичном сайте вовсе необязательно. Можно делать всё по старинке обычными чанками вообще без подключения скриптов и стилей — это уже вам решать.

Публикация дополнения


Когда мы создали все свои модели, таблицы, контроллеры и прочее, наступает время выгрузить новое дополнение для установки на сайтах. Обязательно соберите фронтенд перед выгрузкой — юзеры не смогут подключиться к вашему контейнеру с Node!

Дальше 2 варианта: публичное или приватное приложение.

Для публичных используем репозиторий на Github, а потом указываем его ссылку на packagist.org.



Приватные проекты хранятся в приватных репозиториях, и для доступа к ним вам нужно будет настроить свой composer.json по инструкции.

Заключение


Вот такой коротенький рассказ про разработку новых дополнений. Теперь у вас больше нет причин не пробовать разработать что-то по-номому!

Вот готовый код, скрипт для переименования в ваш уникальный проект — дальше можно воплощать любую фантазию и публиковать готовый пакет для распространения.

Ваше дополнение не обязано быть публичным. Оно запросто может быть уникальным, сделанным под заказ для клиента, и управлять всеми нужными для него вопросами.

Например, я уже сделал таким способом небольшой магазин для одного заказчика. Раньше там было оформление заказов через FormIt и SimpleCart, а теперь собственный компонент:



Я снова могу разрабатывать что-то в MODX!

Ссылка на код заготовки — github.com/bezumkin/mmx-app.
Ссылка на презентацию в Белграде — file.modx.pro/files/9/7/1/9710a725c5fd155ae6932ea37557f8b7.pdf.

Вопросы можно задавать в комментариях.

Обновлено 24.04.2024


Попробовал записать скринкаст по разработке



Обновлено 28.05.2024


В итоге записал целый курс на 5 видосов:
Василий Наумкин
23 апреля 2024, 06:16
modx.pro
3
1 874
+22

Комментарии: 11

Иван Бочкарев
23 апреля 2024, 08:57
+4
Как всегда, на уровне! Спасибо!

  • Очень интересно услышать как в целом прошла конференция?
  • Что интересно из докладов было?
  • Как твой новый предложенный метод восприняли слушатели?
  • Может есть какие новости по развитию MODX?
    Василий Наумкин
    23 апреля 2024, 10:17
    +5
    Всё прошло очень хорошо, парни из Sterc привезли с собой оператора, который всё заснял и зафотал. Сейчас это дело смонтируют и выпустят документалку, можно будет посмотреть.

    Новостей именно про развитие системы, кроме моего доклада, вроде и не было никаких. Разве что Sterc представили новый портал для поиска работы, связанной с MODX — www.workwithwander.com.

    Мой доклад прошёл очень хорошо, теперь самому интересно посмотреть, как это выглядело со стороны. Особенно народ оживился на словах о том, что можно нанимать сотрудников не из мира MODX, а с более широкого рынка современной PHP разработки.

    В общем, ждём документалку.
    Олег Захаров
    23 апреля 2024, 11:30
    +3
    Совершенно другой уровень разработки.
    Теперь придется переучиваться.
    Нужен новый туториал для разработки на новом подходе.
    Нужна новая документация.
    Примеры разработки сайтов на новом принципе.
    Т.к. пока многое не понятно.

    Спасибо персональное Василию за огромный вклад в развитие MODX.
      Василий Наумкин
      24 апреля 2024, 14:54
      +5
      Давай попробуем вот так — youtu.be/BbyfFDARgZU
        Александр Мельник
        30 апреля 2024, 11:26
        0
        Безусловно, видео со звуком в десятки раз информативнее, чем просто видео. Автору всегда кажется что то что он делает на экране, так очевидно, что ничего и комментировать не нужно. Но как правило, автор ошибается.
        За длинное видео со звуком спасибо.
        Есть много вещей, которые я не понял даже со звуком).

        — эта заготовка для создания ОДНОГО дополнения? Или можно в рамках одного сайта разработать сразу 5 несвязанных друг с другом дополнений?

        — это именно инструмент разработки ДОПОЛНЕНИЙ? Или же я могу так же удобно запустить сайт в докере, разработать нужный мне функционал, но не создавать никаких дополнений, а просто перенести весь код на сервер?

        — я плохо знаю modx 3 и может поэтому мне показалось, что дополнения «на уровне кода» очень слабо связаны с самим modx. Модель вы используете eloquent, контроллеры свои, визуализация своя, ну или скажем vue — шная. И мне показалось, что при таком подходе данные например из модели categories никто другой достать не сможет. Ведь есть что то подобное как modx->getService() и для modx3? Тоесть если захочется дотянутся до категорий извне вашего дополнения, то либо на уровне sql запросов или же создавать xml схему и модель, которую понимает modx и затем следить, чтобы модель eloquent и модель modx всегда были синхронизированы.

        — очень не хватило в видео (но я вижу в загловке видео написано — ПЕРВЫЙ урок, поэтому наверное будет второй и это отлично) показа php сниппета для отображения данных в публичной части. Можно предположить что там внутри чистый laravel, но непонятно какой шаблонизатор используется. Eloquent любит blade, modx имеет свой «квадратно скобочный» шаблонизатор. И если на уровне «админки» еще позволительно каждому разработчику делать что он хочет и как он хочет, то публичная часть в рамках одного сайта должна сохранять некую стандартизацию, а то одни разработчик для показа категорий сделает spa, страницы новостей будет рендерится на сервере и так далее.

        — наверное в следующих видео это станет очевидно, но уточню. Правильно я понял, что КОНЕЧНОЙ целью всех этих действия является получение отдельной директории с исходным кодом дополнения, которую можно взять под контрль версий, разместить на github, затем зарегистрировать репозиторий github как репозиторий composer и затем подключать этот код на сайт с modx через менеджер пакетов composer?
          Василий Наумкин
          30 апреля 2024, 11:46
          +3
          — эта заготовка для создания ОДНОГО дополнения?
          Да

          Или можно в рамках одного сайта разработать сразу 5 несвязанных друг с другом дополнений?
          Наверное можно, но я с трудом могу себе представить как кто-то зачем-то разрабатывает 5 несвязанных дополнений на одном сайте. Это же Docker — сделай 5 проектов и разрабыватывай независимо.

          — это именно инструмент разработки ДОПОЛНЕНИЙ? Или же я могу так же удобно запустить сайт в докере, разработать нужный мне функционал, но не создавать никаких дополнений, а просто перенести весь код на сервер?
          Кто ж тебе помешает?

          Придумано для дополнений, но можно делать и запускать целиком сайты в Docker со своим функционалом.

          Тоесть если захочется дотянутся до категорий извне вашего дополнения, то либо на уровне sql запросов или же создавать xml схему и модель, которую понимает modx и затем следить, чтобы модель eloquent и модель modx всегда были синхронизированы.
          В MODX 3 есть Composer с автозагрузкой, так что модели дополения доступны отовсюду. Можно просто создать сниппет и выбрать все категории вот так:

          $categories = \MMX\Super\Shop\Models\Category::query()->get()->toArray();
          
          return print_r($categories, true);

          непонятно какой шаблонизатор используется
          Это решает автор дополнения, никакого «шаблонизатора по умолчанию» нет.
      Александр Мельник
      09 мая 2024, 19:38
      +1
      Решил ознакомится поближе, вижу вы активно снимаете и выкладываете видео на канале, а это очень подкупает.
      Стало интересно, как вы решаете те проблемы, с которыми я сталкиваюсь при работе с докером и к сожалению сразу же споткнулся об эти же грабли.
      Инсталирую mmx-app как вы указываете в видео. И при таком подходе весь код из директории modx недоступен для редактирования из хостовой машины. Проблема очевидная, ожидаемая и связанная с тем что инсталяция modx происходит внутри контейнера а там пользователь root. И соответственно все файлы которые мы видим в volume тоже может редактировать только root.


      Незнаю, может это не стоит считать проблемой, и вы и не планировали, что файлы в директории modx нуждаются в редактировании, но все же…
      Я для себя решил эту проблему тем, что описывая докерфайл создаю там сразу нерутового пользователя и запускаю контнейнер от его имени. В таком случае файлы, созданные от имени этого пользователя монтируются «наружу» с именем пользователя на хостовой системе, что очень удобно.
      Ну а кстати, зачем я вообще полез править файлы в modx. Админка тупо выдает белый экран. Главная страница сайта открывается, а никакие танцы с бубнами вокруг админки пока не помогли.
        Василий Наумкин
        10 мая 2024, 16:27
        0
        Незнаю, может это не стоит считать проблемой, и вы и не планировали, что файлы в директории modx нуждаются в редактировании, но все же…
        Именно так, да. Тем более, что настроить это сразу универсально никак не получится. Если есть хороший пример конфига — делись!

        Я для себя решил эту проблему тем, что описывая докерфайл создаю там сразу нерутового пользователя и запускаю контнейнер от его имени. В таком случае файлы, созданные от имени этого пользователя монтируются «наружу» с именем пользователя на хостовой системе, что очень удобно.
        А я использую в production образы и хост одной и той же системы — Ubuntu (Debian), поэтому всё работает от одного юзера www-data. А на локальной MacOS проблемы с правами и вовсе нет.

        Ну а кстати, зачем я вообще полез править файлы в modx. Админка тупо выдает белый экран. Главная страница сайта открывается, а никакие танцы с бубнами вокруг админки пока не помогли.
        Скорее всего, MODX просто не может создать директорию с кэшем из-за прав, да.

        Решил ознакомится поближе, вижу вы активно снимаете и выкладываете видео на канале, а это очень подкупает.
        Спасибо на добром слове, планирую продолжать!
          Александр Мельник
          10 мая 2024, 18:53
          +1
          Если есть хороший пример конфига — делись!
          Конкретно в вашей конфигурации добиться того, чтобы файлы, генерируемые внутри контейнеров, редактировались на хост машине можно, понадобится всего 2 шага.
          Первое.
          в Dockerfile которые используется при создании образа для php-fpm добоавить строки,
          RUN echo "root:root" | chpasswd
          RUN useradd -m -p user -s /bin/bash user
          USER user:user
          Здесь мы задаем пароль root для пользователя root, а затем создаем пользователя с именем и группой user (можно любое). ОТ имени этого пользователя будут выполнятся все команды по умолчанию в контейнере, который будет запущен на основании этого образа. Это видно на скрине, что пользователь в контейнере user.

          Но остается возможность, поскольку мы задади пароль для пользователя root переключиться и на него. Теперь когда будет выполнять код из вашего скрипта run-install файлы modx будут созданы уже не рутовым пользователем и смогут редактироваться снаружи.
          Второе. Но есть еще проблема. В репозитории на гитхабе у вас изначально отсутствует директория modx, но она используется в docker-compose файле. Изза этого происходит следующее, при запуске docker compose up --build докер ищет директорию modx, не находит и создает ее. Но здесь очень важно, а где он ее создает. Так вот docker в таком случае создает диреторию modx ВНУТРИ контейнера и только потом прокидывает ее наружу. В таком случае директорию modx получается созданной пользователем root. Добавлю скриншот.

          И получается, что наш пользователь user, который запустит команду установки modx не сможет ничего записать в директорию modx, которую он видит внутри своего контейнера. Но эту проблему легко решить, зная как именно работают неименованные volume в докере. Нужно чтобы пустая директория modx существовала в проекте перед тем, как будет выполнена команда docker compose up, в этом случае докер возьмет ее и примонтирует внутрь каждого контейнера и она (директория) не будет создана рутом. Наверное можно просто создать пустую диркторию, но я знаю что гит не позволяет помещать пустую директорию в отсеживаемую область, для чего используют пустой файл .gitkeep. Если modx умеет устанавливаться в НЕ пустую директорию то это будет решением. Если же не умеет (а скорее всего файл .gitkeep не позволит выполнить команду create project у composer) то директорию можно создавать во время выполнения run-rename, главное чтобы до запуска docker compose.

          Все что написал, предварительно проерил и да, теперь у меня есть возможность редактировать код в директории modx и заработал админка. Не знаю по этой ли причине или нет, но это единственный вариант когда у меня открылась админка сайта на 8080 порту.

          Так же напомню, что вам нужно еще подправить run-rename чтобы он делал копию env файла и переименовывал проект.
          Обратил внимание, что при переименовнии проекта скриптом, нельзя использовать цифры. Причем сам скрипт об этом не предупредил и когда я в качестве имени указал alex-test2 то переименование произошло со сбоем. Что то стало называется alex-test2, а что то alex-test.
            Андрей Степаненко
            11 мая 2024, 12:13
            0
            Только для linux (не mac)
            На linux два вариант работы)))
            — Либо работаешь под root
            — Либо настраиваешь www-data пользователя и под ним работаешь

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

            @Александр Мельник думаю что папка modx не под root, это на хост машина так файлы и папки выглядит))) Они на самом деле под пользователем id которого, отсутствует на хост-машине

            нужно зайти в контейнер с php-fpm и посмотреть id пользователя внутри контенер, и создать такого же пользователя у себя
            id

            Еще вариант
            Как еще можно указать под каким пользователем будет работать контейнер
            github.com/webnitros/facade-app/blob/bcc07c7a823afb70d129fd246471472a698b2ebf/docker-compose.yml#L22
            services:
              app:
                image: 'webnitros/modx-app:latest'
                env_file:
                  - ./.env # variables from the env file are exported when the container starts
                user: '82:82'
            Но опять же это не поможет сильно)) Есть nginx, который все равно будет под www-data создавать файлы)))
            В общем беда на linux по работе с docker)))
              Александр Мельник
              11 мая 2024, 14:20
              +2
              Я для себя нашел решение, такое как описал для Василия. Я не использую образу напрямую из dockerhub, а строю свои образы на их основании. Это позволяет добавить в контейнер своего пользователя, настроить его привелегии и избежать проблем с правами на файлы, генерируемые внутри контейнера.
              А как например работает вы? Вот самый простой пример, нужно запутсить ларавель в контейнерах. По умолчанию считаем (и я всегда придерживаюсь этого правила и на своей локальной машине и на серверах), что раз я использую докер, то значит никаких локально установленных программ не должно быть. Тоесть на нашем компьютере нет своего php, нет своей node или nginx, нет redis и прочих mariadb. Мы запускаем php-fpm контейнер, в нутри которого проброшена директория с файлами laravel. Вам нужно выполнить команду в artisan. Напоминаю, что выполнить локально php artisan мы не можем, у нас просто нет php на машине. Значит нам нужно войти в php-fpm контейнер и там выполнить php artisan make model. Файл будет создан, появится у вас локально в редакторе кода, но редактировать вы его не сможете, потому что он создан пользователем root внутри php-fpm. При такой конфигурации, когда генерация файла происходит «изнутри наружу» и не продуманы заранее эти проблемы с правами, вы не сможете работать с кодом, генерируемым artisan, но если вы создадите файл модели в редакторе вручную, то он будет создан наоборот, «снаружи внутрь» и такой файл будет работать правильно.
              В общем да, докер жутко неидеальный инструмент. И не простой. Его осознанное использование требует высоких навыков системного администрирования линукс серверов, глубоких знаних в работе компьютерных сетей (попробуйте ради интереса получить ip адрес пользователя внутри php запущенного внутри docker compose).
              А лично моя проблема, которая доставляет массу неприятностей в работе, в том что я перфекционист в требованиях к себе. Я не могу пользоваться технологией, пока не разберусь в ней хотя бы на 4- из 5. Искренне завидую тем людям (без иронии), которые умеют просто пойти нагуглить функцию на стекоферфлов и даже не читая ее вставлять в свой код. Или же которые просят какой то там ИИ написать решение. Я не могу) Поэтому приходится дотошно ночами экспериментировать с технологиями, но мне нравится.

              Вот кстати насчет того, что я не любитель магии в программировании. Василий в своих полезных видео рассказывает много интересного, но помоему сейчас его уводит в стороны рассказ о том как работать с eloquent и vesp, последние видео очень мало связаны с modx.
              было бы очень позновательно, если бы вы Василий сделали отступление и рассказали, а как именно код нашего приложения интегрируется и попадает внутрь modx. Для меня например был неприятен момент, когда я редактирую PHP код компонента в директории для этого преднозначенной, это сразу отражается в работе сайта. Да это удобно и полезно, но это НЕЛОГИЧНО. Я ведь видел что проищошла инсталяция нашего приложения через composer а значит весь исходный код должен был переместиться в директорию vendor внутри modx а значит никакие изменения теперь не должны влиять. Ведь так? А влияют. Приятно, но НЕНАВИЖУ МАГИЮ. И приходится построчно изучать все инсталяционные скрипты, докер конфигурации, команды symfony console чтобы понять, откуда магия. И найти что вы так очень хитро манирулируете с симлинками. (кстати почти уверен что будут проблемы при переносе приложения из одной директорию в другую, поскольку симлинки в linux создаются с абсолютными путями). Или тот же фронтенд. Тоже небольшая магия, правишь код уже инсталированного composer приложения а он сразу меняется. Правда от этого гадостного современного фронтенда ты уже морально ожидаешь такого подвоха и ты уже удивляешься меньше чем с php. Но снова приходится искать в коде, что вы подменяете ссылки на подключение скриптов. Так же очень неочевиден роутинг. Я пока только мельком взгялнул и пришел к выводу, что теперь в системе есть аж 3 разных роутера. Прежде всего сам modx стороит свой роутинг на основании неймспейсов компонентов. Потом vue строит свой роутинг, для фронтенда. И потом vesp имеет свою роутинг, на основании slim и наверное fastroute. И есть очень много таких подводных камней. Я не говорю что они сделаны плохо или что я могу лучше, нет. Я просто считают что прежде всего нужно рассказать в видео именно о таких вещах, детально рассмотреть как именно встраивается ваше приложение внутрь modx. А то сейчас вы описываете в видео создание псевдо магазина и это инересно, но это совсем не про modx, а про vue, bootstarp-vue, vesp и так далее. И кстати. а как вам удалсь избежать проблем с несколькими реализациями psr-7? Мельком глянул код и увидел что modx использует реализацию от guzzle, а вы slim овскую. (кстати считаю что слимовская правильный выбор, это наиболее точная реализация стандарта). Ведь теперь в системе есть два класса реализующий один и тот же интерфейс и нельзя будет где то запрашивать иньекцю зависимости по интерфейсу. Хотя может в 3 modx и нет такой возможности.
              В общем, буду благодарен если в одном из следующих видео Василй расскажет детально про магию. В том числе как планируется работать с миграциями, сейчас насколько я понимаю выполнить миграции можно только при установке компонента.
        Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
        11