Рекомендую почитать
книгу про паттерн или вот
этот сайт посмотреть, в частности паттерны стратегия. Тогда думаю все станет намного понятнее, так как сейчас у вас даже вопросы неверные, а вообще без опыта в такие дебри лучше не лезть
Если вкратце то:
Вопрос1 - нужно ли всё равно передавать параметр в конструктор вызываемого контроллера или можно просто вызывать без параметров?
У нас есть контейнер, в нем при запуске приложения мы регистрируем классы (сервисы). При регистрации мы связываем абстракцию (интерфейс) и реализацию (конкретный класс), а также впринципе говорим нашему приложению КАК создать конкретный объект. Потом же мы делаем просто так и получаем готовый объект
// Получаем объект интерфейса из любой точки приложения
$container->get(MyInterface::class);
То есть чтобы такой подход работал, нам надо где то (до запуска приложения) сказать как нам этот интерфейс создать, это мы и делаем с помощью контейнера
$container->register(MyInterface::class, function () {
return new MyConcreteClass('какие то параметры');
});
Вопрос2 - где вообще надо делать $container->get('что-нибудь'); ? В самом контроллере как-то неправильно, наверное - ибо тогда всё равно зависимость. Где это делать?
Во-первых, контроллер это обычный класс, во-вторых принцип DI заключается в том, чтобы у вас классы не зависили от конкретных реализаций и явно ЗАВИСИЛИ от АБСТРАКЦИЙ. Это самое важно что нужно понять. Отвечая на вопрос - брать напрямую из контейнера сервисы надо ЗА сервисами, то есть в сервис провайдере и выше
Ну и кстати современные фреймворки достаточно умны и создают классы необходимые конструктору самостоятельно, если они достаточно простые, более сложные сервисы все равно надо регистрировать.
Вот короче пример написал который впринципе все объясняет, если непонятно спрашивай
interface CartRepository
{
public function add(CartItem $item);
public function getAll();
}
class SessionCartRepository implements CartRepository
{
...
}
class DbCartRepository implements CartRepository
{
...
}
class Cart
{
public function __construct(CartRepository $repository)
{
...
}
public function getTotal()
{
...
}
}
// Service provider
$container->register(CartRepository::class, function ($container) {
if ($user = $container->get('auth')->getUser()) {
$repository = new DbCartRepository($container->get('db'), $user->id)
} else {
$repository = new SessionCartRepository();
}
return $repository;
});
$container->register(Cart::class, function ($container) {
return new Cart($container->get(CartRepository::class));
});