Я пытаюсь реализовать маршрутизатор в моем приложении, используя DI-контейнер.
Итак, у меня есть класс Application, который загружает конфигурацию и имеет экземпляр контейнера DI. Приложение имеет Маршрутизатор как класс обслуживания, созданный DI. Маршрутизатор имеет массив классов Route, Route имеет Action, а Action имеет Target. Цель — Закрытие или имя класса контроллера + имя метода контроллера. Я хочу создать контроллер с помощью DI-контейнера, потому что я хочу внедрить некоторые сервисы.
Вот пример структуры.
Приложение класса { приватный $ контейнер; приватный роутер; публичная функция __construct () { $ this-> container = new DIContainer (); $ this-> container-> add (SomeService :: class, function () { вернуть новый SomeService ($ someConfigParams); }) $ this-> router = $ this-> container-> get (Router :: class); } дескриптор публичной функции ($ uri) { вернуть $ this-> router-> handle ($ uri); } } class Router { приватный $ контейнер; частные $ маршруты; // Массив класса Route, заполненный addRoute публичная функция __construct (контейнер $ контейнер) { $ this-> container = $ container; } публичная функция addRoute ($ uri) { $ маршруты [] = $ this-> container-> make (Route :: class, ['uri' => $ uri]); } дескриптор публичной функции ($ uri) { $ route = $ this-> findRoute ($ uri) -> getAction () -> run () } } class Route { приватный $ контейнер; личное $ action; // экземпляр класса Action, заполненный setAction публичная функция __construct (контейнер $ контейнер) { $ this-> container = $ container; } публичная функция setAction ($ params) { $ this-> action = $ this-> container-> make (Action :: class, $ params); } публичная функция getAction () { вернуть $ this-> action (); } } действие класса { приватный $ контейнер; частный $ target; // Экземпляр класса Target, заполненный setTarget публичная функция __construct (контейнер $ контейнер) { $ this-> container = $ container; } публичная функция setTarget () { $ this-> target = $ this-> container-> make (Targer :: class) } публичная функция run () { return $ this-> target-> run (); } } class Target { приватный $ контейнер; private $ controllerClass; приватный $ controllerMethod; публичная функция __construct (контейнер $ контейнер, $ класс, $ метод) { $ this-> container = $ container; $ this-> controllerClass = $ class; $ this-> controllerMethod = $ method; } публичная функция run () { return $ this-> container-> make ($ this-> controllerClass) -> {$ this-> controllerMethod} (); } } //И наконец! Контроллер класса { private $ someService; публичная функция __construct (SomeService $ someService) { $ this-> someService = $ someService; } проверка публичной функции () { return $ this-> someService-> sayHello (); } } новое приложение () -> дескриптор ('/ controller / test /');
Извините за такой большой пример кода. Но мне действительно интересно, нормально ли, что все классы в цепочке зависят от $ container только потому, что контроллеру нужен сервис. Или я должен просто сделать свой класс Container глобальным (например, singleton) и вызвать его на последнем шаге? Как это:
... // Целевой класс публичная функция run () { return Container :: getInstance () -> make ($ this-> controllerClass) -> {$ this-> controllerMethod} () } ...
Задача ещё не решена.
Других решений пока нет …