MODX. Методы для работы с классами: loadClass(), getService(), addPackage(), addExtensionPackage()

Помимо стандартных php функций для вызова класса, из серии require и include, в MODX также предусмотренны свои методы, реализующие тот же, но более адаптированный функционал: addPackage(), loadClass(), getService(), addExtensionPackage().

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

Код xPDO методов addPackage(), loadClass() и getService() можно найти в файле по адресу core/xpdo/xpdo.class.php. Все три метода, в случае если сталкиваются с ошибкой, записывают ее в логи MODX, и пропускают загрузку класса, если он уже загружен.

Краткое заключение

  • Если вы просто хотите создать экземпляр класса, который не связывается с БД, используйте loadClass(). Обязательно укажите путь и установите для четвертого аргумента значение true, иначе вызов не удастся.
  • Если вы хотите создать экземпляр класса, который представляет из себя объект БД и сгенерировали для него файлы классов и карт, используйте addPackage(). Тогда loadClass() будет вызываться автоматически при вызове с помощью любого объекта xPDO, который обращается к базе данных. Но если вы будете использовать свой класс до того, как произойдет обработка addPackage(), вам придется вызвать loadClass() самостоятельно.
  • Если вы хотите расширить базовый класс MODX, который представляет из себя объект БД, используйте addExtensionPackage().
  • Если вы хотите, чтобы класс был доступен как $modx‑>className, или если класс уже зарегистрирован как сервис MODX (например, modMail, modLexicon, modError), используйте getService(). В последнем случае вам не нужен путь, но если пакет находится в подкаталоге под core/directory, вам необходимо указать его: $modx‑>getService('registry, registry.modRegistry').

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

addPackage() [xPDO]

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

$modx->addPackage('sample', MODX_CORE_PATH . 'components/sample/model/');

 Синтаксис 

boolean addPackage ([string $pkg = ''], [string $path = ''], [string $tablePrefix = ''])
  • $pkg — имя подпапки в пределах $path (обычно совпадает с именем компонента). Подпапка может содержать множество файлов классов your_table.class.php и чаще всего вложенную папку MYSQL в которой размещены дополнительные файлы классов и схем для работы с бд, например your_table.class.php и your_table.map.inc.php. 
  • $path — полный путь до папки компонента, в том числе, имя указанное в первом аргументе.
  • $tablePrefix (не обязательно) — префикс таблицы БД, если он отличается от стандартного префикса данной сборки MODX. Если указать не правильный префикс, компонент не будет правильно функционировать.

При ошибке возвращает false.

После того, как вы зарегистрировали пакет при помощи addPackage(), его связанные с БД объекты будут автоматически вызываться с loadClass() (если класс не был загружен прежде) при попытке получить доступ к ним с любым методом xPDO, таким как newObject(), getObject(), или getCollection(). 

С классами зарегистрированными с addPackage() всегда стоит использовать $modx‑> newObject() для инициализации, вместо new, в этом случае не будет необходимости вызывать loadClass().

Официальная документация метода addPackage().

addExtensionPackage()

В системных настройках MODX есть параметр extension_packages, где содержится JSON массив данных о пакетах, расширяющих базовые классы MODX. Так вот, addExtensionPackage() создан для того, чтобы было удобнее заносить информацию о таких пакетах.

addExtensionPackage() — автоматическое подключение addPackage(), для пакетов расширяющих базовые классы MODX. Для addExtensionPackage() обязательно должно быть наличие модели БД.

Синтаксис

boolean addExtensionPackage ([string $pkg = ''], [string $modelpath = ''], [array $options = array()])
  • $pkg — название папки в директории model/, в большинстве компонентов совпадает с именем пространства имен компонента, но, также,  бывают случаи, когда у компонентов несколько подпапок.
  • $modelpath — путь до каталога model/.
  • $options — дополнительные параметры, например можно указать префикс таблицы БД:
$modx->addExtensionPackage('mypkg', MODX_CORE_PATH . 'components/sample/model/', array('tablePrefix'=>'mypre_'));

removeExtensionPackage()

В дополнение к addExtensionPackage() существует метод removeExtensionPackage(), который удаляет запись из массива extension_packages:

boolean removeExtensionPackage (string $pkg = '')

Официальная документация метода addExtensionPackage().

loadClass() [xPDO]

Метод загружающий классы, но не создающий их экземпляр. Метод заменяющий функции из разряда include и require, для включения *.class.php файлов. Бонусы использования loadClass():

  • если он сталкивается с ошибкой, то записывает ее в журнал ошибок MODX;
  • обеспечивает дополнительный контроль над процессом загрузки, например, позволяет вызвать один и тот же класс, не выдавая ошибки.
  • использует кэш.
$path = MODX_CORE_PATH . 'components/sample/model/';
$modx->loadClass('sample.Sample', $path, true, true);

Синтаксис 

string|boolean loadClass (string $fqn, [ $path = ''], [ $ignorePkg = false], [ $transient = false])
  • $fqn — полное имя класса для загрузки (fully qualified name). Часть после точки должна совпадать с именем класса в файле, а после преобразования в нижний регистр, должна совпадать с именем файла (.class.php будет добавлен автоматически). Имя можно задавать и с другими форматами, об этом ниже. 
  • $path — полный путь к каталогу, содержащему класс.
  • $ignorePkg — если false, MODX ищет во всех подключенных пакетах. Если вы уверенны что addPackage() не вызван, вы можете слегка ускорить процесс обработки, поставив параметр true. Так MODX не будет искать по всем пакетам.
  • $transient — является ли класс временным или нет. Если false, MODX считает что пакет не является временным, а значит хранится в базе данных. Если ваш класс, это объект базы данных, и код будет взаимодействовать с базой данных, он должен быть установлен в false. Если класс не представляет собой объект базы данных, или никогда не читает и не записывает в базу данных, то последний аргумент должен быть установлен в true. 

При ошибке возвращает false.

Если параметр имени указан стандартным способом: 

$fqn = 'login.Login';
$path = MODX_CORE_PATH . 'components/login/model/';
$modx->loadClass($fqn, $path, true, true);

 MODX будет искать файл по адресу:

usr/public_html/modx/core/components/login/model/login/login.class.php

Если указано только имя класса: 

$path = MODX_CORE_PATH . 'components/mycomponent/model/';
$modx->loadClass('MyClass', $path, true, true);

MODX будет искать файл в самом каталоге model/

Если файл с классом находится по адресу /model/utilities/myclass/, то имя будет выглядеть так:

$path = MODX_CORE_PATH . 'components/mycomponent/model/';
$modx->loadClass('utilities.myclass.MyClass', $path, true, true);

Иными словами — точки в имени преобразуются в слешы.

Официальная документация метода loadClass().

getService() [xPDO]

Загружает и возвращает экземпляр класса сервиса (внутри себя использует метод loadClass()). Возвращает ссылку на экземпляр класса или NULL если служба не может быть загружена (класс создается только один раз, последующие вызовы возвращают ссылку на сохраненный экземпляр)

Экземпляр класса добавляется к объекту $modx, благодаря чему его методы можно вызывать подобным образом: $modx‑>className->methodName(). Это, к примеру, полезно если в вашем классе есть метод, переопределяющий метод ядра MODX, тогда к нему можно обратиться так: $modx->sample-><em>getChunk()</em>. Этот метод будет работать внутри другого класса или везде, где доступен объект $modx, хотя класс сервиса доступен только во время запроса, в котором он был загружен как сервис. Для встроенных сервисов MODX можно использовать сокращенную версию: $modx‑>lexicon().

$modx->getService('sample','sample.Sample');

Синтаксис

object getService (string $name, [string $class = ''], [string $path = ''], [array $params = array ()])
  • $name — ключ, идентифицирующий сервис.
  • $class — полное имя класса, совместимого с оператором «new». Также можно использовать «точечную нотацию» для указания подпапок относительно пути из $path.
  • $path — полный путь к каталогу, содержащему класс.
  • $params — параметры передающиеся в массив $scriptProperties. В компонентах передаются как второй аргумент метода __construct. Первый аргумент всегда является ссылкой на xPDO / MODX.

При ошибке возвращает null. Если служба уже была загружена, getService() просто возвращает ссылку на нее. 

Некоторые классы обслуживания, такие как modLexicon и modError, почти всегда доступны в MODX, но не будет лишним еще раз вызвать их с getService(), особенно это критично в коде, работающем вне MODX. Код, работающий за пределами MODX, должен загружать службу ошибок, иначе программа завершится сбоем, если возникнут какие-либо ошибки MODX.

$modx->getService('error', 'modError');
$modx->getService('lexicon', 'modLexicon');
$modx->getService('fileHandler', 'modFileHandler');

Первый аргумент getService(), $name является псевдонимом , который может быть использован для вызова службы. Например, если вы хотите использовать лексикон MODX после того, как служба была создана с помощью getService(), можно сделать это так:

$message = $modx->lexicon('file_not_found');

Для встроенных служб MODX (lexicon, mail, error, registry, и т.д.) не обязательно использовать $path, т.к. этот параметр по умолчанию — core/model/, но если служба находится в подкаталоге, то это придется обозначить:

$modx->getService('registry', 'registry.modRegistry');
$modx->getService('mail', 'mail.modPHPMailer');

Точка во втором параметре превращается в слеш. Запись по правую сторону от последней точки — имя класса, все что слева от последней точки добавляется к пути относительно каталога model/.

Официальная документация метода getService.

tnx

Частично использовались материалы Боба Рэя