Facade Laravel в Modx 2/3

Приветствую! В этом видео я хочу поделиться с вами способом упрощения работы с Modx Revolution, а именно — о том, как подключить Laravel Facade.

Многие разработчики сталкиваются с определенными сложностями при работе с Modx в Ide, и я не исключение. В поисках способов оптимизации процесса я обратил внимание на Laravel Facade — мощный инструмент, который может значительно упростить и ускорить разработку.


В данном видео я поделюсь своим опытом подключения Laravel Facade к Modx Revolution. Я расскажу о шагах, необходимых для успешной интеграции, и поделюсь практическими советами в комментариях по устранению возможных проблем.

Надеюсь, мой опыт будет полезен для всех, кто стремится улучшить свой опыт работы с Modx и сделать процесс разработки более эффективным и приятным. Благодарю за внимание!

Использовал новый компонент mmxFenom для демонстрации работы в Modx 3 (но и для modx 2 то же будет работать)

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



Публикую код в сыром виде
github.com/webnitros/facade-modx
Потом можно и пакет создать на packagist.org/

У себя в проектах много где использовал Facade.
Сейчас больше вопросов про внедрение этого решения в MODX, так как не очень сильно разбирался, как работает MODX 3.
Видел, что добавлена контейнеризация в новой версии MODX, но все равно надо разбираться, как лучше интегрировать это решение.
Андрей Степаненко
07 мая 2024, 09:34
modx.pro
1
2 476
+6
Поблагодарить автора Отправить деньги

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

Василий Наумкин
07 мая 2024, 11:16
0
Лично я терпеть не могу фасады Laravel, и это одна из основных причин, почему мы с ним не сработались.

Дело в том, что при переходе в addModifier здесь, мы попадём в фасад, а не в класс \Fenom, где этот метод и объявлен:

И это жутко бесит, когда пытаешь проследить логику работы.

Уж лучше вызывать нормально класс и подписывать его комментарием, зато никаких проблем с навигацией через IDE.

По моему, это гораздо проще и удобнее, чем городить фасады.

Но, в любом случае, спасибо за заметку. Кому-то, может, такое наоборот удобнее.
    Андрей Степаненко
    07 мая 2024, 11:46
    0
    Понимаю
    Есть такое
    По этому в конце комментариев See оставляется
    use MMX\Fenom\App;
    
    /**
     * @method static void addModifier(string $modifier, callable $callback)
     * @method static void fetch($template, array $vars = [])
     * @see \MMX\Fenom\App
     */
    То же раздражала навигация.

    Спустя какое-то время понял, как ориентироваться, привыкаешь к этому, после того как запомнишь, как функция вызывается и что она делает.

    Для разработки чего-то нового, конечно же, не подходит, лучше обычным методом класс вызывать. Но для кода, который уже не первый год, вот тут выигрываешь сильно.
    Наумов Алексей
    07 мая 2024, 12:32
    +2
    Я тоже пересмотрел, не до конца понял профит (сокращение кол-ва подписей к объектам?).

    Зато увидел усложнение, в виде накрутки над классом фасада, который еще сильнее усложнит жизнь).

    А может у меня проекты такие, где это не нужно, не знаю)
      Андрей Степаненко
      07 мая 2024, 14:37
      +3
      Записал видео, 12 минутное
      Разобрал более подробней работу Facade
      Несколько вариантов представил для сравнения
      Андрей Степаненко
      07 мая 2024, 17:29
      0
      Отлично, у $modx->services еще контракты подходящие

      $modx->services->add('fenom', function (use $modx) {
          return $modx->services->get('mmxFenom');
      });
      Facade::clearResolvedInstances();
      Facade::setFacadeApplication($modx->services);
      
      echo \MODX\Facades\Fenom::fetch('file:chunks/test.tpl', ['name' => 'Hello']);
        Андрей Степаненко
        07 мая 2024, 17:44
        0
        @Василий Наумкин подскажи плиз, Facades из коробки получается работают в modx 3?

        core/src/Facades/Fenom.php
        <?php
        namespace MODX\Facades;
        
        use Illuminate\Support\Facades\Facade;
        use MMX\Fenom\App;
        
        /**
         * @method static void addModifier(string $modifier, callable $callback)
         * @method static void fetch($template, array $vars = [])
         * @see App
         */
        class Fenom extends Facade
        {
            protected static function getFacadeAccessor(): string
            {
                return 'mmxFenom';
            }
        }


        Для запуска

        <?php
        
        use Illuminate\Support\Facades\Facade;
        define('MODX_API_MODE', true);
        require 'index.php';
        
        
        Facade::clearResolvedInstances();
        Facade::setFacadeApplication($modx->services);
        
        echo \MODX\Facades\Fenom::fetch('file:chunks/test.tpl', ['name' => 'Hello']);
          Василий Наумкин
          07 мая 2024, 18:48
          +1
          Если установлены через composer, то да, будет автозагрузка.

          Судя по коду ты их просто положил в namespace MODX, так что да, так тоже работает.
        Андрей Степаненко
        08 мая 2024, 09:37
        0
        Нашел альтернативное решение для написания комментариев к функциям, чтобы можно было в два клика добраться до неё.

        Для modx @see \modX::getOption
        <?php
        namespace FacadeApp\Facades;
        use Illuminate\Support\Facades\Facade;
        /**
         * @method static mixed getOption($key, $options = null, $default = null, $skipEmpty = false)
         * @see \modX::getOption
         * @see modX
         */
        class ModX extends Facade
        {
            protected static function getFacadeAccessor(): string
            {
                return 'modx';
            }
        }

        Для pdoTools @see \pdoTools::getChunk

        <?php
        namespace FacadeApp\Facades;
        
        use Illuminate\Support\Facades\Facade;
        
        /**
         * @method static string getChunk($name = '', array $properties = array(), $fastMode = false)
         * @see \pdoTools::getChunk
         * @see modX
         */
        class Pdo extends Facade
        {
            protected static function getFacadeAccessor(): string
            {
                return 'modx';
            }
        }


        Cобрал пакеn по старинке через modExtra
        Github: github.com/webnitros/facade-app

        На модерацию уже отправил в modstore

        Кому интересно, disk.yandex.ru/d/EtmO2tOPCYC6xA

        Работает как в Modx 2 так и в 3 версии
        Проверил на обоих версиях, одинаково отрабатывает код
        # modx 2 и 3 запуск одинаковый
        $site = \FacadeApp\Facades\ModX::getOption('site_name');
        
        echo '<pre>';
        print_r($site);
        die;

        С composer все еще могут возникать проблемы совместимости.

        Еще событие добавил FacadeAppAddSingleton чтобы свои фасады можно было добавить github.com/webnitros/facade-app/blob/master/FACADE.md
          Андрей Степаненко
          08 мая 2024, 09:53
          0
          По идее, если бы в MODX в обе версии интегрировать эти фасады, можно было бы добиться какого-то моста между версиями для совместимости других дополнений.

          К примеру вызов того же pdotools в версии modx 2 сделать по максимум чтобы все вызывалось через Facade
          Тогда при установке на modx 3 этого компонента, была бы обратная совместимость. Опять же не прям всех классов и функций, но таких которые являются базовыми (наивное предположение конечно же))).
            Александр Мельник
            09 мая 2024, 21:25
            0
            Тоесть я так понял, что в modx3 так и не завезли никакого контейнера зависимостей и нормальной автоматической иньекции зависимостей? Я помню когда только шли обсуждения что выйдет modx3 говорили что будет применена какая то там библиотека для контейнера зависимостей. Я еще возмущался, почему не phpDi, а мне сказали что та библиотека даже более крутая.
            А судя по вашему коду, сервисы все еще из $modx достаются? Печально.
            Честно говоря, тоже не люблю фасады и не пользуюсь ими и в ларавель. Выглядит как сотый уровень абстракции над абстракцией, без которой вполне можно обойтись. Лучшее враг хорошего, хотя это лично мое мнение.
              Андрей Степаненко
              10 мая 2024, 18:33
              0
              Контейнеризация есть
              github.com/modxcms/revolution/commits/3.x/core/src/Revolution/Services/Container.php

              Её и использовал для подключение Facade в 3 версии modx
              github.com/webnitros/facade-app/blob/2fe0344f87806bead554ba8f91e1d3d1ad62bb7f/Extras/FacadeApp/core/components/FacadeApp/elements/plugins/FacadeApp.php#L47C52-L47C53

              $modx->services # Все что в сервисах, это контейнеры modx 3
              Проблема в другом
              # Так буде работать
              $modx->services->get('mmxFenom')->fetch($tpl, ['resources' => $resources]);
              
              # Так нет
              \MMX\Fenom\App::fetch($tpl, ['resources' => $resources]); 
              
              # Если с Facade, это аналог: $modx->services->get('mmxFenom')->fetch($tpl, ['resources' => $resources])
              \MMX\Fenom\Facade::fetch($tpl, ['resources' => $resources]);
              это сам класс не позволяет делать, его нужно затачивать под такой вызов чтобы он инстанс вызывал который уже например инциализирован, чтобы постоянной инициализации класса занова небыло

              Другой вариант контенеризации это сделать app() какой то, который будет обращаться к контенерам как будто
              $modx->services->get('mmxFenom')

              @Сергей Шлоков уже довольно давно, предлагал изменить getInstance,
              // Здесь https://github.com/modxcms/revolution/blob/fe2df183eabfebfd66c2c6f2788f2b93c40d4d1b/core/src/Revolution/modX.php#L410
               // Это  
              $class = __CLASS__; 
              # заменяем на это
              $class = class_exists($id) ? $id : __CLASS__;
              и тогда можно обращаться вот так:
              modX::getInstance('modX')->getOption('site_name');
              Кстати, где возможно, в свои проекты внедрил эту практику, работает отлично, без контейнеризации. Я не оценивал последствия, если это сделать стандартной сборке MODX 3 или 2, может там будут проблемы с процессорами. Но эта практика modX::getInstance('modX'), как и с Facade, упрощает написание кода.

              Тогда можно будет сделать вот так
              \MMX\Fenom\App::fetchNew($tpl, ['resources' => $resources]); 
              Или вот так
              \MMX\Fenom\App::instance()->fetch($tpl, ['resources' => $resources]);
                Андрей Степаненко
                10 мая 2024, 18:53
                0
                Короче)) пока modx не начнет вызываться вот так:
                app()->getOption('site_name')
                Ни какого прогресса не будет
                Сергей Шлоков
                11 мая 2024, 10:06
                +1
                Если сказать, что с такими мейнтейнерами как Джейсон, MODX будет загибаться быстрее, чем без них, то это будет уже миллионное повторение. Он потушил энтузиазм многих активных модыксеров, которые в итоге перешли в другие лагеря разработки.

                Я в своё время его спросил, нафига добавлять контейнер Pimple, разработка и поддержка которого прекращена? Почему не взять развивающийся и более навороченный PHP-DI? Насколько я помню, он ответил какую-то чушь в стиле — зато легкая, а нам больше и не нужно. Даже Марк тогда присоединился к моему вопросу. Но Джейсон сказал, что переделывать он ничего не будет. Это было ещё до выпуска релиза MODX3, когда можно было хорошо почистить легаси.
              Андрей Степаненко
              10 мая 2024, 19:06
              0
              Ставлю бутылку))) Начинающему или среднем программисту до лампочи как там работает Fenom, там хрен разберешься (по себе знаю).
              А вот вызов fenom, через чур усложнен, по этому хотя бы через Facade стоит прокинуть, как и многие другие сервисы.

              Собственно Facade не требует ни какой дополнительно зависимости, mmxFenom уже устанавливает illuminate support где есть Facade
                Arthur
                10 мая 2024, 19:30
                0
                Я вообще не знаю, где класс Fenom находится
                  Василий Наумкин
                  12 мая 2024, 06:41
                  +1
                  Так ты сделай нормальное composer дополнение для MODX — и пусть его себе ставит кто хочет, вместе с остальными mmx-дополнениями. Древний транспортный пакет тут совсем ни к чему.

                  Есть же заготовка — просто используй.
                  Любовь
                  27 ноября 2024, 10:31
                  0
                  Извините, у вас сообщения закрыты. Я хотела спросить насчет компонента msExportUsersExcel. Может быть у вас есть аналогичный компонент для импорта пользователей?
                    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                    23