Используем системный composer в MODX 3

Привет.
Одно из самых заметных изменений в MODX 3 это наличие системного Composer для установки своих зависимостей.

Что такое Composer из зачем он нужен ?

Composer — это менеджер для подключения и управления этими сторонними библиотеками или пакетами в вашем PHP-проекте который решает следующие проблемы:

  1. Быстрая установка и обновление пакетов
  2. Резолвинг зависимостей между пакетами
  3. Хранение пакетов и их версии в едином файле без необходимости версионировать все пакеты вручную

Как установить Composer?

Мануалов по установке Composer под каждую систему достаточно много. Самый актуальный и самый понятный (внезапно) находится на официальном сайте Composer по адресу

Так как Composer это обыкновенный PHP скрипт, то для его работы потребуется локально установленный PHP. В Windows окружениях это может быть PHP входящий в состав OpenServer/Denwer/прочей аутдейтед дичи которую вы используете, так и глобально установленный для Windows.

В Linux окружениях Composer можно нередко встретить в составе пакетных менеджеров ваших систем.
Например в Ubuntu можно поставить Composer даже не имея установленного PHP. Наберите в терминале следующую команду:
sudo apt install composer
Если PHP не установлен в систему то APT самостоятельно поставит вам последнюю доступную версию PHP в репозиториях вашей системы.

В macOS есть установленный PHP по умолчанию в рамках установленной системы. Однако использовать его не рекомендуется. Composer, php и прочие радости жизни можно установить с помощью Homebrew, но можно использовать входящий в состав MAMP.

Используем Composer в рамках MODX

Вообще с помощью composer MODX 3 можно даже установить.

composer create-project modx/revolution .
Данной командой мы говорим что хотим создать новый проект MODX, а точка в конце говорит о том, что мы хотим установить проект в текущую папку.

Ответ на эту команду будет примерно вот такой:
Creating a "modx/revolution" project at "./"
Info from https://repo.packagist.org: #StandWithUkraine
Installing modx/revolution (v3.0.0-pl)
  - Installing modx/revolution (v3.0.0-pl): Extracting archive
Created project in /Applications/MAMP/htdocs/.
Loading composer repositories with package information
Info from https://repo.packagist.org: #StandWithUkraine
Updating dependencies
Lock file operations: 67 installs, 0 updates, 0 removals
  - Locking aws/aws-crt-php (v1.0.2)
  - Locking aws/aws-sdk-php (3.219.2)
  - Locking doctrine/instantiator (1.4.1)
  - Locking erusev/parsedown (1.7.4)
  - Locking guzzlehttp/guzzle (7.4.2)
  - Locking guzzlehttp/promises (1.5.1)
  - Locking guzzlehttp/psr7 (2.2.1)
  - Locking inlinestyle/inlinestyle (1.2.7)
  - Locking james-heinrich/phpthumb (v1.7.17)
  - Locking league/flysystem (2.4.3)
  - Locking league/flysystem-aws-s3-v3 (2.4.3)
  - Locking league/mime-type-detection (1.10.0)
  - Locking mtdowling/jmespath.php (2.6.1)
  - Locking myclabs/deep-copy (1.11.0)
  - Locking nikic/php-parser (v4.13.2)
  - Locking phar-io/manifest (2.0.3)
  - Locking phar-io/version (3.2.1)
  - Locking phpdocumentor/reflection-common (2.2.0)
  - Locking phpdocumentor/reflection-docblock (5.3.0)
  - Locking phpdocumentor/type-resolver (1.6.1)
  - Locking phpmailer/phpmailer (v6.6.0)
  - Locking phpspec/prophecy (v1.15.0)
  - Locking phpunit/php-code-coverage (9.2.15)
  - Locking phpunit/php-file-iterator (3.0.6)
  - Locking phpunit/php-invoker (3.1.1)
  - Locking phpunit/php-text-template (2.0.4)
  - Locking phpunit/php-timer (5.0.3)
  - Locking phpunit/phpunit (9.5.20)
  - Locking pimple/pimple (v3.5.0)
  - Locking psr/container (2.0.2)
  - Locking psr/http-client (1.0.1)
  - Locking psr/http-factory (1.0.1)
  - Locking psr/http-message (1.0.1)
  - Locking ralouphie/getallheaders (3.0.3)
  - Locking sebastian/cli-parser (1.0.1)
  - Locking sebastian/code-unit (1.0.8)
  - Locking sebastian/code-unit-reverse-lookup (2.0.3)
  - Locking sebastian/comparator (4.0.6)
  - Locking sebastian/complexity (2.0.2)
  - Locking sebastian/diff (4.0.4)
  - Locking sebastian/environment (5.1.4)
  - Locking sebastian/exporter (4.0.4)
  - Locking sebastian/global-state (5.0.5)
  - Locking sebastian/lines-of-code (1.0.3)
  - Locking sebastian/object-enumerator (4.0.4)
  - Locking sebastian/object-reflector (2.0.4)
  - Locking sebastian/recursion-context (4.0.4)
  - Locking sebastian/resource-operations (3.0.3)
  - Locking sebastian/type (3.0.0)
  - Locking sebastian/version (3.0.2)
  - Locking simplepie/simplepie (1.5.8)
  - Locking smarty/smarty (v4.1.0)
  - Locking symfony/console (v5.4.7)
  - Locking symfony/css-selector (v6.0.3)
  - Locking symfony/deprecation-contracts (v3.0.1)
  - Locking symfony/polyfill-ctype (v1.25.0)
  - Locking symfony/polyfill-intl-grapheme (v1.25.0)
  - Locking symfony/polyfill-intl-normalizer (v1.25.0)
  - Locking symfony/polyfill-mbstring (v1.25.0)
  - Locking symfony/polyfill-php73 (v1.25.0)
  - Locking symfony/polyfill-php80 (v1.25.0)
  - Locking symfony/service-contracts (v3.0.1)
  - Locking symfony/string (v6.0.3)
  - Locking theseer/tokenizer (1.2.1)
  - Locking webmozart/assert (1.10.0)
  - Locking xpdo/xpdo (v3.1.0)
  - Locking yoast/phpunit-polyfills (0.2.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 67 installs, 0 updates, 0 removals
  - Downloading symfony/deprecation-contracts (v3.0.1)
  - Downloading league/mime-type-detection (1.10.0)
  - Downloading league/flysystem (2.4.3)
  - Downloading aws/aws-sdk-php (3.219.2)
  - Downloading league/flysystem-aws-s3-v3 (2.4.3)
  - Downloading phpmailer/phpmailer (v6.6.0)
  - Downloading sebastian/environment (5.1.4)
  - Downloading simplepie/simplepie (1.5.8)
  - Downloading smarty/smarty (v4.1.0)
  - Downloading symfony/service-contracts (v3.0.1)
  - Downloading xpdo/xpdo (v3.1.0)
  - Installing aws/aws-crt-php (v1.0.2): Extracting archive
  - Installing symfony/polyfill-mbstring (v1.25.0): Extracting archive
  - Installing erusev/parsedown (1.7.4): Extracting archive
  - Installing symfony/deprecation-contracts (v3.0.1): Extracting archive
  - Installing psr/http-message (1.0.1): Extracting archive
  - Installing psr/http-client (1.0.1): Extracting archive
  - Installing ralouphie/getallheaders (3.0.3): Extracting archive
  - Installing psr/http-factory (1.0.1): Extracting archive
  - Installing guzzlehttp/psr7 (2.2.1): Extracting archive
  - Installing guzzlehttp/promises (1.5.1): Extracting archive
  - Installing guzzlehttp/guzzle (7.4.2): Extracting archive
  - Installing symfony/css-selector (v6.0.3): Extracting archive
  - Installing inlinestyle/inlinestyle (1.2.7): Extracting archive
  - Installing james-heinrich/phpthumb (v1.7.17): Extracting archive
  - Installing league/mime-type-detection (1.10.0): Extracting archive
  - Installing league/flysystem (2.4.3): Extracting archive
  - Installing mtdowling/jmespath.php (2.6.1): Extracting archive
  - Installing aws/aws-sdk-php (3.219.2): Extracting archive
  - Installing league/flysystem-aws-s3-v3 (2.4.3): Extracting archive
  - Installing myclabs/deep-copy (1.11.0): Extracting archive
  - Installing phar-io/version (3.2.1): Extracting archive
  - Installing phar-io/manifest (2.0.3): Extracting archive
  - Installing phpdocumentor/reflection-common (2.2.0): Extracting archive
  - Installing phpdocumentor/type-resolver (1.6.1): Extracting archive
  - Installing symfony/polyfill-ctype (v1.25.0): Extracting archive
  - Installing phpmailer/phpmailer (v6.6.0): Extracting archive
  - Installing sebastian/recursion-context (4.0.4): Extracting archive
  - Installing sebastian/exporter (4.0.4): Extracting archive
  - Installing sebastian/diff (4.0.4): Extracting archive
  - Installing sebastian/comparator (4.0.6): Extracting archive
  - Installing webmozart/assert (1.10.0): Extracting archive
  - Installing phpdocumentor/reflection-docblock (5.3.0): Extracting archive
  - Installing doctrine/instantiator (1.4.1): Extracting archive
  - Installing phpspec/prophecy (v1.15.0): Extracting archive
  - Installing theseer/tokenizer (1.2.1): Extracting archive
  - Installing sebastian/version (3.0.2): Extracting archive
  - Installing nikic/php-parser (v4.13.2): Extracting archive
  - Installing sebastian/lines-of-code (1.0.3): Extracting archive
  - Installing sebastian/environment (5.1.4): Extracting archive
  - Installing sebastian/complexity (2.0.2): Extracting archive
  - Installing sebastian/code-unit-reverse-lookup (2.0.3): Extracting archive
  - Installing phpunit/php-text-template (2.0.4): Extracting archive
  - Installing phpunit/php-file-iterator (3.0.6): Extracting archive
  - Installing phpunit/php-code-coverage (9.2.15): Extracting archive
  - Installing phpunit/php-invoker (3.1.1): Extracting archive
  - Installing phpunit/php-timer (5.0.3): Extracting archive
  - Installing psr/container (2.0.2): Extracting archive
  - Installing pimple/pimple (v3.5.0): Extracting archive
  - Installing sebastian/cli-parser (1.0.1): Extracting archive
  - Installing sebastian/code-unit (1.0.8): Extracting archive
  - Installing sebastian/object-reflector (2.0.4): Extracting archive
  - Installing sebastian/global-state (5.0.5): Extracting archive
  - Installing sebastian/object-enumerator (4.0.4): Extracting archive
  - Installing sebastian/resource-operations (3.0.3): Extracting archive
  - Installing sebastian/type (3.0.0): Extracting archive
  - Installing simplepie/simplepie (1.5.8): Extracting archive
  - Installing smarty/smarty (v4.1.0): Extracting archive
  - Installing symfony/polyfill-php73 (v1.25.0): Extracting archive
  - Installing symfony/polyfill-php80 (v1.25.0): Extracting archive
  - Installing symfony/service-contracts (v3.0.1): Extracting archive
  - Installing symfony/polyfill-intl-normalizer (v1.25.0): Extracting archive
  - Installing symfony/polyfill-intl-grapheme (v1.25.0): Extracting archive
  - Installing symfony/string (v6.0.3): Extracting archive
  - Installing symfony/console (v5.4.7): Extracting archive
  - Installing xpdo/xpdo (v3.1.0): Extracting archive
  - Installing phpunit/phpunit (9.5.20): Extracting archive
  - Installing yoast/phpunit-polyfills (0.2.0): Extracting archive
22 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
42 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
> @php -r "file_exists('_build/build.properties.php') || copy('_build/build.properties.sample.php', '_build/build.properties.php');"
> @php -r "file_exists('_build/build.config.php') || copy('_build/build.config.sample.php', '_build/build.config.php');"
> @php _build/transport.core.php
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Beginning build script processes...
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Removed pre-existing core/ and core.transport.zip.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Core transport package created.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Core Namespace packaged.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Default workspace packaged.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged modx.com transport provider.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in 2 modMenus.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged all default modContentTypes.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in 190 default events.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in 229 default system settings.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in 2 default context settings.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in 1 default user groups.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in 1 default dashboards.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in 1 default media sources.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in 7 default dashboard widgets.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in 2 default roles Member and SuperUser.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in 7 default Access Policy Template Groups.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in 7 default Access Policy Templates.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in 12 default Access Policies.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in web context.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in mgr context.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Packaged in connectors.
[2022-04-13 13:48:10] (INFO @ _build/transport.core.php) Beginning to zip up transport package...
[2022-04-13 13:48:11] (INFO @ _build/transport.core.php) Transport zip created. Build script finished.

Execution time: 1.0460 s
Далее можно проследовать по адресу <хост_вашего_сервера>/setup или же побыть хакером и осуществить установку системы с помощью командной строки

Итак, у нас есть чистая система. Давайте попробуем подтянуть какой-нибудь Composer пакет и попробуем его использовать.Частая жопаболь при разработке каких либо систем — работа с датой, временем и таймзонами.
Давайте попробуем установить компонент Carbon который облегчает нам эту задачу.

composer require nesbot/carbon
Данная команда установит нам пакет Carbon в наш проект. Вы можете удостовериться в этом, когда увидите в вашем файле composer.json (в корне сайта)

"require": {
        "nesbot/carbon": "^2.16"
    }
Результат выполенения команды будет следующий:
Info from https://repo.packagist.org: #StandWithUkraine
Using version ^2.57 for nesbot/carbon
./composer.json has been updated
Running composer update nesbot/carbon
Loading composer repositories with package information
Info from https://repo.packagist.org: #StandWithUkraine
Updating dependencies
Lock file operations: 3 installs, 0 updates, 0 removals
  - Locking nesbot/carbon (2.57.0)
  - Locking symfony/translation (v6.0.7)
  - Locking symfony/translation-contracts (v3.0.1)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 3 installs, 0 updates, 0 removals
  - Downloading symfony/translation-contracts (v3.0.1)
  - Installing symfony/translation-contracts (v3.0.1): Extracting archive
  - Installing symfony/translation (v6.0.7): Extracting archive
  - Installing nesbot/carbon (2.57.0): Extracting archive
2 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
45 packages you are using are looking for funding.
Use the `composer fund` command to find out more!



В многих гайдах по использованию Composer пакетов вы найдете следующий сниппет кода:

<?php
require 'vendor/autoload.php';
Это справедливо, если используете Composer в своих проектах отдельно, но в MODX за нас это уже сделал наш файл index.php

Давайте попробуем создать сниппет со следующим содержанием и попробуем вызвать наш компонент.



Такс, че тут происходит?

Ключевое слово use должно быть указано строго в начале файла или же внутри внутри пространства имен
use создает псевдоним для более удобного использования класса из пространства имен.

Конечно, нам никто не запрещает написать вот так и не использовать ключевое слово use.
\Carbon\Carbon::now()
Однако писать каждый раз пространство класса может быть достаточно утомительным занятием.
Carbon может вызываться статичеки, так и с помощью конструктора класса. Чтобы было проще, будем вызывать статические методы.
Давайте вызовем наш сниппет в стандартном шаблоне который идет вместе с установкой MODX.

Ожидаемый результат:


Классно!
У нас все получилось.

Что ж нам делать если нужно все таки вызвать конструктор класса?

По факту варианта два.
Первый — каждый раз вызывать конструктор в сниппете (или где угодно где вы вызваете вашу библитеку).
Давайте изменим ваш сниппет и узнаем какой завтра день :D

<?php
use Carbon\Carbon;

$carbon = new Carbon();
$carbon->addDay();
return $carbon->dayName;
Тут мы вызываем новый экземпляр Carbon и возвращаем имя дня в наш сниппет.
Чем же плох такой вариант? Да по факту ничем. Однако, если таких вызовов на странице будет множество, то вы попросту потратите память зря. А что делать если вы хотите создать экземпляр единожды и работать с ним дальше сквозь всю систему?
Использовать вторую важную особенность в MODX 3 — внедрение зависимостей.
Но об этом как-нибудь в другой раз :)

Cheers!
Павел Бигель
13 апреля 2022, 18:35
modx.pro
2
1 797
+23
Поблагодарить автора Отправить деньги

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

Евгений Webinmd
13 апреля 2022, 18:59
+1
На самом интересном месте!!!
    Алексей Смирнов
    14 апреля 2022, 09:18
    +1
    Интрига удалась. Жду продолжения. )
      vectorserver
      15 апреля 2022, 06:26
      0
      Неплохо!
      Самый простой способ внедрить зависимости не залезая в пространство имен, выполнить команду:
      <?php
      $modx->addExtensionPackage('mypkg', '/path/to/core/components/mypkg/model/', array('tablePrefix'=>'mypre_'));
        Павел Бигель
        19 апреля 2022, 03:03
        0
        Данный способ актуален только для двойки.
        DI который прикрутили в тройке совсем другой
        Роман
        16 апреля 2022, 10:46
        +1
        Спасибо за статью. Доступно, понятно, с хорошим чувством юмора.
          Stepan
          29 ноября 2023, 15:35
          0
          Такое использование composer возможно только если MODX установлен из composer(не пробовал)
          в обратном случае если вы попробуете установить пакет в core при помощи composer то потеряете половину ядра если не более....
          наверное есть смысл в index.php добавлять ссылку на кастомный autoload.php куда и ставить пакеты…
          ЗЫ
          не туда ответил, но может кому и пригодится
          Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
          6