Услуги
Введение
Все основные классы в CodeIgniter предоставляются в виде «услуг». Это означает, что вместо жесткой привязки имени класса для загрузки, классы для вызова определяются в очень простом файле конфигурации. Этот файл действует как фабрика для создания новых экземпляров требуемого класса.
Быстрый пример, вероятно, прояснит ситуацию. Представьте, что вам нужно получить экземпляр класса Timer. Самый простой способ — создать новый экземпляр этого класса:
$timer = new \CodeIgniter\Debug\Timer();
И это отлично работает. До тех пор, пока вы не решите использовать другой класс таймера вместо него. Возможно, этот класс обладает расширенными функциями отчетности, которых нет у стандартного таймера. Для этого вам нужно найти все места в вашем приложении, где используется класс таймера. Поскольку вы, возможно, оставили их, чтобы постоянно вести журнал производительности вашего приложения, это может быть затратным и подверженным ошибкам способом решения этой проблемы. Именно здесь услуги становятся полезными.
Вместо того, чтобы создавать экземпляр самостоятельно, мы позволяем центральному классу создать для нас экземпляр класса. Этот класс остается очень простым. Он содержит только метод для каждого класса, который мы хотим использовать как услугу. Метод обычно возвращает общий экземпляр этого класса, передавая в него необходимые зависимости. Затем мы заменяем наш код создания таймера кодом, вызывающим этот новый класс:
$timer = \Config\Services::timer();
Когда вам нужно изменить используемую реализацию, вы можете изменить файл конфигурации услуг, и изменения автоматически происходят во всем приложении, без необходимости каких-либо действий с вашей стороны. Теперь вам просто нужно воспользоваться новыми функциями, и все готово. Очень просто и устойчиво к ошибкам.
Примечание
Рекомендуется создавать службы только внутри контроллеров. Другие файлы, такие как модели и библиотеки, должны получать зависимости либо через конструктор, либо через метод-сеттер.
Удобные функции
Для получения услуги предоставляются две функции. Эти функции всегда доступны.
Первая — service() — возвращает новый экземпляр запрошенной услуги. Единственный необходимый параметр — имя услуги. Это совпадает с именем метода в файле Services, всегда возвращающим ОБЩИЙ экземпляр класса, поэтому вызов функции несколько раз всегда должен возвращать один и тот же экземпляр:
$logger = service('logger');
Если метод создания требует дополнительных параметров, их можно передать после имени услуги:
$renderer = service('renderer', APPPATH . 'views/');
Вторая функция, single_service() работает так же, как service() , но возвращает новый экземпляр класса:
$logger = single_service('logger');
Определение услуг
Для эффективной работы с услугами необходимо полагаться на каждый класс, имеющий постоянный API или интерфейс. Почти все классы CodeIgniter предоставляют интерфейс, которому они соответствуют. При расширении или замене базовых классов необходимо лишь убедиться, что вы удовлетворяете требованиям интерфейса, и вы знаете, что классы совместимы.
Например, класс RouterCollection реализует интерфейс RouterCollectionInterface. Если вы хотите создать замену, которая обеспечивает другой способ создания маршрутов, вам нужно создать новый класс, который реализует интерфейс RouterCollectionInterface:
class MyRouter implements \CodeIgniter\Router\RouteCollectionInterface
{
// Implement required methods here.
}
Наконец, измените /app/Config/Services.php, чтобы создать новый экземпляр MyRouter вместо CodeIgniter\Router\RouterCollection:
public static function routes()
{
return new \App\Router\MyRouter();
}
Разрешение параметров
В некоторых случаях вам может потребоваться возможность передачи значения в класс во время его инициализации. Поскольку файл services — очень простой класс, это легко реализуется.
Хороший пример — служба renderer. По умолчанию мы хотим, чтобы этот класс мог находить представления в APPPATH.views/. Однако мы хотим предоставить разработчику возможность изменения этого пути, если это необходимо. Таким образом, класс принимает $viewPath в качестве параметра конструктора. Метод службы выглядит следующим образом:
public static function renderer($viewPath=APPPATH.'views/')
{
return new \CodeIgniter\View\View($viewPath);
}
Это задает путь по умолчанию в методе конструктора, но позволяет легко изменить используемый путь:
$renderer = \Config\Services::renderer('/shared/views');
Общие классы
Иногда требуется, чтобы создавался только один экземпляр службы. Это легко обрабатывается с помощью метода getSharedInstance() , вызываемого из метода фабрики. Он обрабатывает проверку, создан ли экземпляр и сохранен ли он в классе, и если нет, создает новый. Все методы фабрики принимают значение $getShared = true в качестве последнего параметра. Следует придерживаться этого метода:
class Services
{
public static function routes($getShared = false)
{
if (! $getShared)
{
return new \CodeIgniter\Router\RouteCollection();
}
return static::getSharedInstance('routes');
}
}
Обнаружение служб
CodeIgniter может автоматически обнаруживать любые файлы Config\Services.php, которые вы создали в любых определенных именах пространств. Это позволяет просто использовать любые модульные файлы Services. Для обнаружения пользовательских файлов Services необходимо выполнить следующие условия:
- Имя пространства должно быть определено в
Config\Autoload.php - Внутри пространства файл должен быть найден по адресу
Config\Services.php - Он должен расширять
CodeIgniter\Config\BaseService
Небольшой пример должен прояснить это.
Представьте, что вы создали новую директорию Blog в корневой директории. Это будет модуль blog с контроллерами, моделями и т. д., и вы хотите предоставить некоторые классы как услугу. Первый шаг — создать новый файл: Blog\Config\Services.php. Структура файла должна быть следующей:
<?php
namespace Blog\Config;
use CodeIgniter\Config\BaseService;
class Services extends BaseService
{
public static function postManager()
{
// ...
}
}
Теперь вы можете использовать этот файл как описано выше. При получении службы записей из любого контроллера вы просто используете класс фреймворка Config\Services для получения вашей службы:
$postManager = Config\Services::postManager();
Примечание
Если несколько файлов Services содержат одно и то же имя метода, будет возвращен первый найденный экземпляр.
© 2014–2020 British Columbia Institute of Technology
Licensed under the MIT License.
https://codeigniter.com/user_guide/concepts/services.html