Использование MODX вне MODX3

Перевод заметки Using MODX Outside of MODX3

В одной из статей было рассмотрено создание экземпляра объекта $modx в эпоху до MODX3. В этой статье мы рассмотрим использование MODX вне MODX Revolution 3. Большая часть кода такая же, как и в предыдущей статье (прим. переводчика: предыдущая статья не переведена, так как немного не актуальна в рамках перехода на модх3). Основное отличие состоит в том, что MODX Revolution 3 широко использует пространства имен и имеет автозагрузчик для загрузки классов.


Код



<?php
namespace MODX\Revolution;

use xPDO\xPDO;
use MODX\Revolution\Error\modError;

$cliMode = false;
$outsideModx = false;

/* Set a user (set to an actual username) */
$myUserName = 'JoeBlow';

/* Instantiate MODX if necessary */

/* See if we're in MODX or not */
$inModx = isset($modx) && $modx instanceof modX;

/* All the code below will only execute if
   we're not in MODX */
if (!$inModx) {
    $outsideModx = true;

    /* Correct this path to point to the config.core.php file
       in the MODX root directory! */
    require "c:/xampp/htdocs/modx3/config.core.php";

    /* Set path to config.inc.php
       (minus the filename) -- Note that this
       has to be corrected if the config directory
       is not directly under the core directory */
    $configPath = MODX_CORE_PATH .
        MODX_CONFIG_KEY . '/';

    /* Check for CLI mode and set log target */
    if (php_sapi_name() == 'cli') {
        $cliMode = true;
        $logTarget = 'ECHO';
    } else {
        $logTarget = 'HTML';
    }

    /* get the vendor autoload file */
    require_once MODX_CORE_PATH . "vendor/autoload.php";

    /* Constants below have to come after
       getting the autoloader */

    /* Set Log Level; options are:
       LOG_LEVEL_FATAL, LOG_LEVEL_ERROR,
       LOG_LEVEL_WARN, LOG_LEVEL_INFO,
       and LOG_LEVEL_DEBUG  */

  /* (If you don't send a log level,
     MODX will set it to LOG_LEVEL_ERROR) */
  $logLevel = xPDO::LOG_LEVEL_INFO;

  $options = array(
    'log_level' => $logLevel,
    'log_target' => $logTarget,
  );

     /* instantiate the $modx object */
    $modx = new modX($configPath, $options);

    if (!$modx instanceof modX) {
        die('Could not create MODX class');
    }

    $modx->initialize('web');
    // $modx->initialize('mgr');

    /* Initialize $modx->error */
    if (!$modx->services->has('error')) {
        $modx->services->add('error', new modError($modx));
    }
    $modx->error = $modx->services->get('error');

    /* Make sure there's a request */
    $modx->getRequest();

    /* Set $modx->resource to home page */
    $homeId = $modx->getOption('site_start');
    $homeResource = $modx->getObject('modResource', $homeId);

    if ($homeResource instanceof modResource) {
        $modx->resource = $homeResource;
    } else {
        die('No Resource');
    }

    /* set $modx->user */
    $myUser = $modx->getObject('modUser',
        array('username' => $myUserName));
    if ($myUser instanceof modUser) {
        $modx->user = $myUser;
    } else {
        die('No User');
    }
}

Убедитесь, что все работает


После того, как вы создали файл с приведенным выше кодом, вы можете выполнить его из командной строки или в редакторе кода. Если нет ошибок, то он работает.

Пространства имен — Namespaces


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

namespace MODX\Revolution;

use xPDO\xPDO;
use MODX\Revolution\Error\modError;

Пространство имен, используемое для всего MODX — MODX\Revolution. Это гарантирует, что любой код, который ссылается на объект или метод MODX, использует правильный объект, а не объект с таким же именем в дополнении MODX, пользовательском плагине/сниппете или какой-либо библиотеке, используемой MODX (например, mail(), cURL или guzzle).

Два оператора use сообщают PHP, где найти класс xPDO и класс modError, поэтому нам не нужно подключать файлы этих классов дополнительно. Обратите внимание, что в отличие от MODX2, нам также не нужно подключать файл класса modX.

Вся эта магия работает с помощью автозагрузчика, который мы загружаем перед использованием констант xPDO для журнала логов и перед созданием объекта $modx. Как только мы «включили» файл автозагрузчика, мы можем использовать практически любой объект MODX по имени, без необходимости подключать файл класса.

Создание $modx объекта


Для создания MODx объекта необходимо использовать строку:
$modx = new modX($configPath, $options);

Мы передаем конструктору MODX два аргумента.
Первый ($configPath) — это путь к конфигурационному файлу MODX (config.inc.php) без имени файла.
Второй ($options) — это массив $options, который мы установили ранее, содержащий настройки журнала логов.
Оба аргумента являются необязательными, но эффективнее отправлять их, так как в противном случае MODX может сделать несколько попыток найти их, и часто будет устанавливать неправильные настройки журнала для наших целей.

Если мы не передадим аргумент $options, нам также придется вызывать $modx->setLogTarget() и $modx->setLogLevel() позже в нашем коде, чтобы убедиться, что они установлены правильно, что означает, что они оба вызываются дважды, один раз в конструкторе и снова в нашем коде.

Мне действительно нужно все это?


Комментарии в приведенном выше коде говорят сами за себя, но они не объясняют, почему мы делаем то, что делаем, и когда это необходимо.

Не для всех задач необходимо использовать весь код, хотя и его использование не принесет каких-либо проблем. Для простого сниппета часто требуется только первая часть кода (до строки $modx->initialize() включительно).

Инициализация MODX


Первая часть кода проверяет, существует ли уже объект $modx. Нет смысла его создавать, если он уже есть.

Выбор инициализации MODX в контексте «web» или «mgr» зависит от того, что делает ваш код. В большинстве случаев это не имеет значения, но если ваш код вызывает процессоры, которые проверяют разрешения, или если ваш код проверяет разрешения напрямую, MODX будет использовать Политику, привязанную к пользовательской группе пользователя для указанного контекста при выполнении проверок.

В целях безопасности использование «web», как правило, предпочтительнее, поскольку у пользователя меньше шансов иметь разрешения в этом контексте, которые позволят ему натворить бед.

$outsideModx и $cliMode


Код выше устанавливает переменную $outsideModx на тот случай, если нам нужно будет узнать позже в сценарии, работаем ли мы внутри MODX или нет. Мы также устанавливаем переменную $cliMode. Это указывает, выполняется ли сценарий из командной строки или в браузере. Мы также устанавливаем настройки журнала MODX, чтобы сообщения $modx->log() были правильно отформатированы.

Внутри MODX $cliMode всегда будет ложным, поэтому проверка находится внутри раздела, который работает только за пределами MODX (поэтому мы установили его в значение true над этим разделом). При работе вне MODX $cliMode будет иметь значение true, только если скрипт запускается из командной строки или из редактора программирования, и значение false, если он выполняется в браузере. Это важно знать, потому что в режиме CLI HTML-код будет отображаться, а не выполняться, и будет загромождать вывод.

Если вы работаете в режиме CLI и вам нужно, например, распечатать сообщение об ошибке, вы можете использовать такой код (убрать у br пробелы):
if ($cliMode) {
    echo "\nFile not found";
} else {
    echo '< br >File not found';
}
Приведенный выше код предполагает, что ваш файл кода находится внутри установки MODX, хотя он не обязательно должен быть в корне. Код все еще будет работать, если он находится в другом каталоге, если пути правильные. В этом случае ваш редактор кода (например, PhpStorm) пометит множество операторов использования классов и операторов пространства имен как ошибки, потому что не может их найти, но код все равно будет работать.

Если у вас много вывода, вы, вероятно, использовали бы функцию для вывода сообщений, возможно, используя nl2br() для преобразования новых строк в теги разрыва.

$error, $request, $resource, и $user


Трудно сказать наверняка, когда они понадобятся. Вы можете делать в своем скрипте вещи, которые будут напрямую или косвенно обращаться к различным объектам MODX. Если вы вызываете процессор, например, с помощью $modx->runProcessor(), велики шансы, что процессор вызовет одно или два события. Во многих вызовах событий $modx->resource или $modx->user используются совместно. Если их нет, программа может зависнуть.

Вы можете подумать, что эти настройки не нужны, если вы не вызываете никаких процессоров или каких-либо событий, но помните, что код работает так, как если бы он был внутри MODX. Это означает, что любой из плагинов сайта может вступить в игру. Одним из них может быть проверка $modx->user или $modx->resource. Он также может просматривать текущий запрос или выдавать ошибку с помощью обработчика ошибок MODX.

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

Приведенный выше код устанавливает $modx->resource на страницу, указанную в системных настройках site_start. Если ваш код будет общедоступен, это безопасно, потому что он используется практически на каждом сайте. Для закрытого кода вы можете создать фиктивный ресурс, чтобы у плагинов не было возможности обращаться к домашней странице (например, плагин DefaultResourceGroup).

Если ваш код не использует ресурсы, вы можете удалить этот раздел.

Если вы используете Ресурсы, но не сохраняете их, вы, вероятно, можете удалить этот раздел, но будьте готовы вернуть его в случае сбоя кода.

Вам необходимо изменить приведенный выше код, чтобы изменить «JoeBlow» на имя реального пользователя. В целях безопасности лучше не устанавливать для него права администратора, если вам не нужны разрешения этого пользователя для выполнения вашего кода. Если вы будете распространять свой код, вам придется принять решение о том, использовать ли администратора (ID = 1), создать пользователя, выбрать случайного пользователя или посоветовать людям самим установить имя пользователя.

У вас может возникнуть соблазн использовать (анонимного) пользователя, но это не настоящий пользователь, и вызов getObject() завершится ошибкой. Вы можете установить пользователя (анонимного), заменив весь код пользователя выше простым вызовом ниже, но имейте в виду, что разрешения пользователя могут быть слишком ограничены для вашего варианта использования.
$modx->getUser();

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

Как и в случае с $modx->resource, если ваш код вообще не связан с пользователями, вы можете удалить этот раздел.

Подводя итоги


На практике я обычно использую весь приведенный выше код. Затраты времени минимальны, и вы никогда не знаете, когда новый компонент, плагин или сниппет потребует какой-то его части. Я помещаю код в файл с именем initialize-modx.php и «включаю» его вверху своего кода.
Евгений Webinmd
05 апреля 2022, 01:12
modx.pro
3
1 548
+14

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

Павел Голубев
05 апреля 2022, 11:28
0
Спасибо, полезно.
    Илья Уткин
    06 апреля 2022, 16:37
    +2
    Прошу прощения за оффтоп, но… Они что, все статьи Боба Рэя с 2013 года публикуют как свеженькие в 2022 году? modx.com/blog/ten-essential-extras-to-make-modx-yours — свеженькая статья, которая рассказывает о таком чудесном дополнении, как getResources =)))
      Василий Наумкин
      06 апреля 2022, 18:26
      +3
      А ты что хотел, чтобы американцы про российский pdoTools рассказывали?

      Правда, народ на запрещённом сайте тоже недоумевает
        Николай Савин
        06 апреля 2022, 18:55
        0
        Вась, давай обойдемся без лишних упоминаний запрещенки. Очень прошу.
        Miša Bulic
        07 апреля 2022, 00:41
        0
        Seo suite такой пук в лужу если честно. Позиционируют себя как главное Seo дополнение для modx, а тег canonical до сих пор не исправлен issue висит с 2021 года. В общем установив его на рабочий сайт можно из выдачи вылететь нахрен.
      Сергей Шлоков
      07 апреля 2022, 06:52
      +6
      Мда. Я надеюсь, что лайки поставили автору за труды, а не за это творчество (код). Лично мне, чтобы понять уровень, достаточно этого
      /* See if we're in MODX or not */
      $inModx = isset($modx) && $modx instanceof modX;
      
      /* All the code below will only execute if
         we're not in MODX */
      if (!$inModx) {
          $outsideModx = true;
         ...
      Код выше устанавливает переменную $outsideModx на тот случай, если нам нужно будет узнать позже в сценарии, работаем ли мы внутри MODX или нет.
      Т.е. переменная $inModx показывает, что мы внутри MODX. А переменная $outsideModx, которая является обратной к $inModx, показывает, что мы снаружи. Шикарно, правда?

      А получение ресурса и пользователя указанными методами говорит о том, что автор не понимает как это работает внутри.
        Николай Савин
        07 апреля 2022, 09:11
        0
        Код действительно почти бессмысленный. Но такой контент полезен для портала в любом случае. Лучше уж так, чем писать месяцами идеальную статью
          Павел Гвоздь
          07 апреля 2022, 09:42
          0
          А что там идеального то в нормальном коде? Лучше уж никак, чем писать такой низкокачественный код. Потом когда работаешь с такими сайтами, половина времени (не преувеличение) уходит, чтобы разобраться, что и как работает.

          Приведённый Сергеем кусок кода отлично описывает уровень кодера. Это не то, что бессмысленно, это даже уже не смешно…
            Николай Савин
            07 апреля 2022, 10:33
            +3
            Давайте так. Напишите оба по полезной, качественной статье сюда на modx.pro, а эту удалим. Я думаю автор будет не против такого размена. Идет?
              Павел Гвоздь
              07 апреля 2022, 10:37
              0
              Нормально ты припахал) Как-нибудь потом…
            Сергей Шлоков
            07 апреля 2022, 15:06
            0
            Нет, код не бессмысленный. Просто не очень качественный.
          Сергей Шлоков
          07 апреля 2022, 15:06
          0
          Я думал, что это какой-то разработчик с форума, который недавно открыл для себя MODX. А оказывается это Боб Рей. Удивлён. (
            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
            13