diff --git a/en/extending-modx/di-container/index.md b/en/extending-modx/di-container/index.md index 8f59e828b..b42c704ea 100644 --- a/en/extending-modx/di-container/index.md +++ b/en/extending-modx/di-container/index.md @@ -4,6 +4,8 @@ title: Dependency Injection Container MODX 3 introduces a Dependency Injection Container, based on [Pimple 3](https://github.com/silexphp/Pimple), that holds core services and custom services. +`$modx->getService()` still works but is deprecated. Register new services with `add()` / `get()` here instead of `getService()`. See [modX.getService](extending-modx/modx-class/reference/modx.getservice). + The container is available in `modX:$services`, meaning it is typically accessible in one of the following ways: - `$modx->services` (in snippets, plugins, etc) diff --git a/en/extending-modx/modx-class/reference/modx.getservice.md b/en/extending-modx/modx-class/reference/modx.getservice.md index 28138dd8d..b77c1b3c8 100644 --- a/en/extending-modx/modx-class/reference/modx.getservice.md +++ b/en/extending-modx/modx-class/reference/modx.getservice.md @@ -1,38 +1,36 @@ --- title: "modX.getService" -description: "getService load and return a named service class instance" +description: "getService loads a named service class. Deprecated in 3.x in favour of the DI container." --- ## modX::getService -**Note**: getService pushed to xPDO layer +**Deprecated in MODX 3.x.** xPDO marks `getService()` as deprecated and points you at the service / DI container (`$modx->services`). PhpStorm therefore warns that it will be removed in 3.1. That removal **did not happen**. The method still exists on current 3.x, and the core still calls it. Prefer `$modx->services` in new code. See [Dependency Injection Container](extending-modx/di-container). -Load and return a named service class instance. Returns either a reference to the service class instance or null if it could not be loaded. You can think of this is a simple dependency injector. - -Note that the class is instantiated only once: subsequent calls return a reference to the stored instance. +`getService` lives on xPDO (modX extends xPDO). It loads and returns a named service instance, or `null` if it cannot load the class. The instance is created once. Later calls return the stored object. Internally 3.x stores that object in `$modx->services` as well. ## Syntax -API Doc: [modX::getService()](http://api.modx.com/revolution/2.2/db_core_model_modx_modx.class.html#%5CmodX::getService()) - ``` php object getService (string $name, [string $class = ''], [string $path = ''], [array $params = array ()]) ``` -- `$name` _(string)_ a key which uniquely identifies the service. -- `$class` _(string)_ the full name of the class compatible with the "new" operator OR you can use "dot notation" to specify sub-folders relative to `$path` -- `$path` _(string)_ full path to the directory containing the class in question. -- `$params` _(array)_ passed as the 2nd argument to the constructor. The first argument is always a reference to xPDO/MODX. +- `$name` _(string)_ key that identifies the service. +- `$class` _(string)_ class name for `new`, or dot notation for subfolders under `$path`. +- `$path` _(string)_ directory that contains the class file. +- `$params` _(array)_ second constructor argument. The first argument is always the xPDO/MODX instance. + +Defined in [`xPDO::getService()`](https://github.com/modxcms/xpdo/blob/3.x/src/xPDO/xPDO.php). -## Examples +## Examples (still work) -Get the modSmarty service. +Get the Smarty service: ``` php $modx->getService('smarty','smarty.modSmarty'); ``` -Get a custom, user-defined service called 'modTwitter' from a custom path ('/path/to/modtwitter.class.php'), and pass in some custom parameters. +Custom service with a path and constructor params: ``` php $modx->getService('twitter','modTwitter','/path/to/',array( @@ -41,23 +39,56 @@ $modx->getService('twitter','modTwitter','/path/to/',array( $modx->twitter->tweet('Success!'); ``` -Another example of using getService inside a custom Extra: +Inside an Extra: ``` php -// Use path to point directly to the relevant sub-dir: +// Path points at the class directory: if(!$Product = $this->modx->getService('mypkg.product','Product',MODX_CORE_PATH.'components/mypkg/model/mypkg/')) { return 'NOT FOUND'; } -// Or use dot-notation in the classname and point the $path to the model directory: +// Or use dot notation and point $path at the model directory: if(!$Product = $this->modx->getService('mypkg.product','mypkg.Product',MODX_CORE_PATH.'components/mypkg/model/')) { return 'NOT FOUND'; } ``` -getService may have trouble with PHP namespaces. +`getService` can struggle with PHP namespaces. Pass a fully qualified class name, or register the object on the container yourself. + +## Replacement in MODX 3 + +Use `$modx->services` (`has` / `add` / `get`). Core does the same in `modX::runProcessor()` for lexicon and error. + +Register a core-style service (example: `modError`): + +``` php +use MODX\Revolution\Error\modError; + +if (!$modx->services->has('error')) { + $modx->services->add('error', new modError($modx)); +} +$modx->error = $modx->services->get('error'); +``` + +Custom Extra: instantiate the class (Composer / namespace autoload) and add it. A [Namespace `bootstrap.php`](extending-modx/namespaces) is the usual place: + +``` php +$modx->services->add('twitter', function($c) use ($modx) { + return new MyPackage\Twitter($modx, ['api_key' => 3212423]); +}); +``` + +Then: + +``` php +$twitter = $modx->services->get('twitter'); +$twitter->tweet('Success!'); +``` + +`modError` (`$modx->error`) and `modErrorHandler` (`$modx->errorHandler`) are different services. Do not mix the keys. ## See Also -- [modX](extending-modx/core-model/modx "modX") -- [MODX Services](extending-modx/services "MODX Services") -- [xPDO.loadClass](extending-modx/xpdo/class-reference/xpdo/xpdo.loadclass "xPDO.loadClass") – similar to getService, but it just loads the class and doesn't instantiate it. +- [modX](extending-modx/core-model/modx) +- [MODX Services](extending-modx/services) +- [Dependency Injection Container](extending-modx/di-container) +- [xPDO.loadClass](extending-modx/xpdo/class-reference/xpdo/xpdo.loadclass) loads a class without instantiating it diff --git a/en/extending-modx/services/index.md b/en/extending-modx/services/index.md index a43ff5f64..355144658 100644 --- a/en/extending-modx/services/index.md +++ b/en/extending-modx/services/index.md @@ -6,15 +6,15 @@ _old_uri: "2.x/developing-in-modx/advanced-development/modx-services" ## What is a Service? -A service is any object that is loaded via [$modx->getService](extending-modx/modx-class/reference/modx.getservice "modX.getService"). It can be a custom class provided by the user, or by MODX itself. +A service is any object stored in the [dependency injection container](extending-modx/di-container) (`$modx->services`). In 2.x, and still in 3.x, many extras also load services with [$modx->getService](extending-modx/modx-class/reference/modx.getservice). That helper is deprecated in 3.x. Prefer `has` / `add` / `get` on `$modx->services`. -Once an object is loaded with getService, it is accessible via `$modx->(servicename)`. So, for example: +Once a service is in the container, you can also hang it on `$modx` yourself (`$modx->error = $modx->services->get('error')`). `getService` did that automatically. ``` php -$modx->getService('twitter','myTwitter','/path/to/twitter/model/',array( - 'api_key' => 3212423, -)); -$modx->twitter->tweet('Success!'); +$modx->services->add('twitter', function($c) use ($modx) { + return new MyPackage\Twitter($modx, ['api_key' => 3212423]); +}); +$modx->services->get('twitter')->tweet('Success!'); ``` ## What are the Default Included Services? @@ -27,4 +27,5 @@ A list of the core-included MODX Services is as follows: ## See Also -- [modX.getService](extending-modx/modx-class/reference/modx.getservice "modX.getService") +- [modX.getService](extending-modx/modx-class/reference/modx.getservice) +- [Dependency Injection Container](extending-modx/di-container) diff --git a/en/getting-started/upgrading-to-3.0/class-names.md b/en/getting-started/upgrading-to-3.0/class-names.md index 7dae91297..ebfca74dd 100644 --- a/en/getting-started/upgrading-to-3.0/class-names.md +++ b/en/getting-started/upgrading-to-3.0/class-names.md @@ -15,6 +15,8 @@ You may encounter warnings or errors (including fatal errors) in certain cases: Most model and service classes that are loaded through `$modx->loadClass` (which includes the xPDO Query builder for model classes) or `$modx->getService` will still work, as `loadClass` internally translates these to their new class names. +`$modx->getService()` itself is **deprecated** in 3.x. xPDO phpdoc (and therefore PhpStorm) still say it will be removed in 3.1. That did not happen: the method remains, and the core still uses it. For new code, register and fetch objects on `$modx->services`. See [modX.getService](extending-modx/modx-class/reference/modx.getservice) and the [DI container](extending-modx/di-container). + For example `$modx->getIterator('modResource')` will still work - _for now_, even though the `\modResource` class is now `\MODX\Revolution\modResource`. That will log a deprecated message to your error log encouraging you to update your reference. The right call would be `$modx->getIterator(\MODX\Revolution\modResource::class)`. diff --git a/en/getting-started/upgrading-to-3.0/index.md b/en/getting-started/upgrading-to-3.0/index.md index c8778ca7b..4ce7dbb3d 100644 --- a/en/getting-started/upgrading-to-3.0/index.md +++ b/en/getting-started/upgrading-to-3.0/index.md @@ -21,6 +21,7 @@ After upgrading the core and upgrading your extras, you may encounter some break - [A list of breaking changes can be found here](getting-started/upgrading-to-3.0/breaking-changes), most notably [many core classes have been moved and renamed](getting-started/upgrading-to-3.0/class-names) - [The manager language is now dynamic](getting-started/upgrading-to-3.0/manager-language) - [Various system settings have been removed or changed](getting-started/upgrading-to-3.0/system-settings) +- `$modx->getService()` is deprecated in favour of the [DI container](extending-modx/di-container) (`$modx->services`). The method still works and was **not** removed in 3.1. See [modX.getService](extending-modx/modx-class/reference/modx.getservice). ## Other notable changes and improvements diff --git a/ru/extending-modx/di-container/index.md b/ru/extending-modx/di-container/index.md index 4b3a12880..7848f0543 100644 --- a/ru/extending-modx/di-container/index.md +++ b/ru/extending-modx/di-container/index.md @@ -5,6 +5,8 @@ translation: "extending-modx/di-container/config" MODX 3 представляет контейнер для инъекций зависимости, основанный на [Pimple 3](https://github.com/silexphp/Pimple), который содержит сервисы ядра и кастомные сервисы. +`$modx->getService()` ещё работает, но устарел. Новые сервисы регистрируйте через `add()` / `get()`, а не через `getService()`. См. [modX.getService](extending-modx/modx-class/reference/modx.getservice). + Контейнер доступен в `modX:$services`, что означает, что он обычно доступен одним из следующих способов: - `$modx->services` (в snippets, plugins, и так далее) diff --git a/ru/extending-modx/modx-class/reference/modx.getservice.md b/ru/extending-modx/modx-class/reference/modx.getservice.md index 485b36713..9c6556c94 100644 --- a/ru/extending-modx/modx-class/reference/modx.getservice.md +++ b/ru/extending-modx/modx-class/reference/modx.getservice.md @@ -1,39 +1,37 @@ --- title: "modX.getService" translation: "extending-modx/modx-class/reference/modx.getservice" -description: "getService() загружает и возвращает экземпляр именованного класса обслуживания" +description: "getService() загружает именованный сервис. В 3.x метод устарел в пользу DI-контейнера." --- ## modX::getService -**Примечание**: getService перемещен на уровень xPDO +**Устарел в MODX 3.x.** xPDO помечает `getService()` как deprecated и отправляет к контейнеру сервисов (`$modx->services`). PhpStorm из-за phpdoc предупреждает об удалении в 3.1. Удаления **не было**. Метод есть в текущих 3.x, ядро само его ещё вызывает. В новом коде берите `$modx->services`. См. [Контейнер внедрения зависимостей](extending-modx/di-container). -Загружает и возвращает экземпляр именованного класса обслуживания. Возвращает ссылку на экземпляр класса обслуживания или значение null, если он не может быть загружен. Вы можете подумать, что это простая инъекция зависимости. - -Обратите внимание, что экземпляр класса создается только один раз: последующие вызовы возвращают ссылку на сохраненный экземпляр. +`getService` живёт в xPDO (modX его наследует). Загружает и возвращает экземпляр сервиса или `null`, если класс не поднялся. Экземпляр создаётся один раз. Повторные вызовы отдают тот же объект. В 3.x он ещё кладётся в `$modx->services`. ## Синтаксис -API Doc: [modX::getService()](http://api.modx.com/revolution/2.2/db_core_model_modx_modx.class.html#%5CmodX::getService()) - ``` php object getService (string $name, [string $class = ''], [string $path = ''], [array $params = array ()]) ``` -- `$name` _(string)_ ключ, который однозначно идентифицирует службу. -- `$class` _(string)_ полное имя класса, совместимого с оператором "new", ИЛИ вы можете использовать "точечную нотацию" для указания вложенных папок относительно `$path`. -- `$path` _(string)_ полный путь к каталогу, содержащему рассматриваемый класс. -- `$params` _(array)_ передается в качестве второго аргумента в конструктор. Первый аргумент всегда является ссылкой на xPDO/MODX. +- `$name` _(string)_ ключ сервиса. +- `$class` _(string)_ имя класса для `new` или точечная нотация для подпапок относительно `$path`. +- `$path` _(string)_ каталог с файлом класса. +- `$params` _(array)_ второй аргумент конструктора. Первый всегда экземпляр xPDO/MODX. + +Определение: [`xPDO::getService()`](https://github.com/modxcms/xpdo/blob/3.x/src/xPDO/xPDO.php). -## Примеры +## Примеры (по-прежнему работают) -Получение сервиса `modSmarty`. +Сервис Smarty: ``` php $modx->getService('smarty','smarty.modSmarty'); ``` -Получить пользовательский, определенный пользователем сервис под названием 'modTwitter' из пользовательского пути ('/path/to/modtwitter.class.php'), и передать некоторые пользовательские параметры. +Свой сервис с путём и параметрами конструктора: ``` php $modx->getService('twitter','modTwitter','/path/to/',array( @@ -42,23 +40,56 @@ $modx->getService('twitter','modTwitter','/path/to/',array( $modx->twitter->tweet('Успех!'); ``` -Еще один пример использования getService внутри пользовательского Extra: +В Extra: ``` php -// Используйте путь, чтобы указать непосредственно на соответствующий вложенный каталог: +// Путь сразу в каталог класса: if(!$Product = $this->modx->getService('mypkg.product','Product',MODX_CORE_PATH.'components/mypkg/model/mypkg/')) { return 'НЕ НАЙДЕН'; } -// Или используйте точечную нотацию в имени класса и укажите $path на каталог модели: +// Или точечная нотация и $path на каталог модели: if(!$Product = $this->modx->getService('mypkg.product','mypkg.Product',MODX_CORE_PATH.'components/mypkg/model/')) { return 'НЕ НАЙДЕН'; } ``` -У `getService` могут возникнуть проблемы с пространствами имен PHP. +У `getService` бывают проблемы с PHP-пространствами имён. Передайте FQCN или зарегистрируйте объект в контейнере сами. + +## Замена в MODX 3 + +Используйте `$modx->services` (`has` / `add` / `get`). Ядро так делает в `modX::runProcessor()` для lexicon и error. + +Регистрация сервиса ядра (пример: `modError`): + +``` php +use MODX\Revolution\Error\modError; + +if (!$modx->services->has('error')) { + $modx->services->add('error', new modError($modx)); +} +$modx->error = $modx->services->get('error'); +``` + +Свой Extra: создайте класс (Composer / autoload namespace) и добавьте его. Обычно это [`bootstrap.php` пространства имён](extending-modx/namespaces): + +``` php +$modx->services->add('twitter', function($c) use ($modx) { + return new MyPackage\Twitter($modx, ['api_key' => 3212423]); +}); +``` + +Дальше: + +``` php +$twitter = $modx->services->get('twitter'); +$twitter->tweet('Успех!'); +``` + +`modError` (`$modx->error`) и `modErrorHandler` (`$modx->errorHandler`) это разные сервисы. Ключи не путайте. ## Смотрите также -- [modX](extending-modx/core-model/modx "modX") -- [MODX Services](extending-modx/services "MODX Services") -- [xPDO.loadClass](extending-modx/xpdo/class-reference/xpdo/xpdo.loadclass "xPDO.loadClass") – similar to getService, but it just loads the class and doesn't instantiate it. +- [modX](extending-modx/core-model/modx) +- [MODX Services](extending-modx/services) +- [Контейнер внедрения зависимостей](extending-modx/di-container) +- [xPDO.loadClass](extending-modx/xpdo/class-reference/xpdo/xpdo.loadclass) загружает класс без создания экземпляра diff --git a/ru/extending-modx/services/index.md b/ru/extending-modx/services/index.md index ead76bc22..43660b588 100644 --- a/ru/extending-modx/services/index.md +++ b/ru/extending-modx/services/index.md @@ -5,15 +5,15 @@ translation: "extending-modx/services" ## Что такое сервис? -Сервис - это любой объект, который загружается через [$modx->getService](extending-modx/modx-class/reference/modx.getservice "modX.getService"). Это может быть пользовательский класс, предоставленный пользователем, или самим MODX. +Сервис это объект в [контейнере внедрения зависимостей](extending-modx/di-container) (`$modx->services`). В 2.x и по-прежнему в 3.x многие extras грузят сервисы через [$modx->getService](extending-modx/modx-class/reference/modx.getservice). Этот хелпер в 3.x устарел. Берите `has` / `add` / `get` у `$modx->services`. -Как только объект загружен с помощью getService, он доступен через `$modx->(servicename)`. Так, например: +Когда сервис уже в контейнере, его можно повесить на `$modx` вручную (`$modx->error = $modx->services->get('error')`). `getService` делал это сам. ``` php -$modx->getService('twitter','myTwitter','/path/to/twitter/model/',array( - 'api_key' => 3212423, -)); -$modx->twitter->tweet('Success!'); +$modx->services->add('twitter', function($c) use ($modx) { + return new MyPackage\Twitter($modx, ['api_key' => 3212423]); +}); +$modx->services->get('twitter')->tweet('Success!'); ``` ## Какие сервисы включены по умолчанию? @@ -26,4 +26,5 @@ $modx->twitter->tweet('Success!'); ## Смотрите также -- [modX.getService](extending-modx/modx-class/reference/modx.getservice "modX.getService") +- [modX.getService](extending-modx/modx-class/reference/modx.getservice) +- [Контейнер внедрения зависимостей](extending-modx/di-container) diff --git a/ru/getting-started/upgrading-to-3.0/class-names.md b/ru/getting-started/upgrading-to-3.0/class-names.md index c44aed059..1d2181b56 100644 --- a/ru/getting-started/upgrading-to-3.0/class-names.md +++ b/ru/getting-started/upgrading-to-3.0/class-names.md @@ -16,6 +16,8 @@ translation: "getting-started/upgrading-to-3.0/class-names" Большинство классов моделей и служб, которые загружаются через `$modx->loadClass` (который включает в себя конструктор запросов xPDO для классов моделей) или `$modx->getService` будет по-прежнему работать, так как `loadClass` внутренне переводит их в свои новые имена классов. +Сам `$modx->getService()` в 3.x **устарел**. phpdoc xPDO (и PhpStorm) всё ещё пишут про удаление в 3.1. Его не удалили: метод на месте, ядро его вызывает. В новом коде регистрируйте и забирайте объекты через `$modx->services`. См. [modX.getService](extending-modx/modx-class/reference/modx.getservice) и [DI-контейнер](extending-modx/di-container). + Для примера `$modx->getIterator('modResource')` все равно будет работать - _пока_, хотя `\modResource` класс сейчас `\MODX\Revolution\modResource`. Это будет регистрировать устаревшее сообщение в журнале ошибок, призывающее вас обновить ссылку. Правильный вызов был бы `$modx->getIterator(\MODX\Revolution\modResource::class)`. diff --git a/ru/getting-started/upgrading-to-3.0/index.md b/ru/getting-started/upgrading-to-3.0/index.md index 31102d31d..b6441fc43 100644 --- a/ru/getting-started/upgrading-to-3.0/index.md +++ b/ru/getting-started/upgrading-to-3.0/index.md @@ -20,6 +20,7 @@ translation: "getting-started/upgrading-to-3.0" - [Список критических изменений](getting-started/upgrading-to-3.0/breaking-changes), в частности [многие классы ядра перенесены и переименованы](getting-started/upgrading-to-3.0/class-names) - [Язык менеджера теперь динамический](getting-started/upgrading-to-3.0/manager-language) - [Различные системные настройки удалены или изменены](getting-started/upgrading-to-3.0/system-settings) +- `$modx->getService()` устарел. Вместо него [DI-контейнер](extending-modx/di-container) (`$modx->services`). Метод всё ещё работает и **не** удалён в 3.1. См. [modX.getService](extending-modx/modx-class/reference/modx.getservice). ## Другие заметные изменения и улучшения