Как реализовать сервисы для контроллера как в Symfony, но с нуля?
Допустим, есть некая mvc система, где action'ы лежат в классах контроллера. И я хочу реализовать передачу каких-то классов из определенного каталога напрямую в метод, например:
public function index(Service $service)
{
return $this->render($service);
}
$service - это объект класса, расположенного в определенном месте (директория Lib, допустим).
Такое можно делать в Symfony, но я не особо понимаю как можно это сделать своими руками с нуля.
Изначально не известно что будет подано в метод, класс Service или какой-то ещё (возможно несколько). При этом объекты не должны создаваться заранее.
Примерный результат:
public function deleteUser(Response $response, Logger $logger, UserRepository $userRepository)
{
.....
$id = $userRepository->getIds()[0];
$userRepository->deleteUser($id);
.....
return $response->send('user '.$id.' deleted');
}
Было бы круто увидеть простой пример реализации или паттерн описывающий такой функционал.
Ответы (1 шт):
Предлагаю ознакомиться с понятием Dependency Injection (внедрение зависимостей).
Но, в общих словах, DI это некий контейнер зависимостей, который вы в своем приложении собираете сами, Symfony от 3-ей версии действительно довольно сахарно реализует внедрение зависимостей.
Представим, что у нас имеется 3 типа классов:
- Классы, у которых сигнатура метода конструктора не определена - вы можете создавать на лету, т.е. при разборе определенного маршрута в ядре вашего приложения, вам нужно проверить (чтобы это проверить, стоить прочитать про рефлексию), что конструктор не имеет параметров и проинтанцировать класс зависимости и отдать его как аргумент в целевой.
- Классы, у которых имеются дефолтные значения в сигнатуре метода конструктора, аналогично, вы можете попробовать сделать инстанс на основе этих, дефолтных значений (ReflectionAPI предоставляет вам эту возможность).
- Классы, у которых в сигнатуре конструктора параметры, представлены другими классами, у которых аналогично другие классы в зависимостях. Тут все сложнее, вы можете парсить в соответствии с PSR-4 директории, искать классы с соответствующим названием и от них искать их зависимости, пытаться зарезолвить их дойдя до базовых классов и используя пункты 1 и 2 пройти всю иерархию снизу вверх.
P.S. Symfony делает примерно что-то подобное.