Где внедрять зависимости?

Вот есть у меня скрипт инициализации MVC - он создаёт и запускает FrontController:

$request = new Request;
$root = $request->getRoot();
$settings = new Settings($root . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR. 'global.php');
$logger = new Logger($root . $settings->logs_dir);


// Loading advanced exception and error handlers
$p_handler = new ProblemHandler($settings->dev_mode, $logger);
$p_handler->setHandlers();

// Pre-configuring PHP and environment
$starter = new Starter;
$starter->prepare();

$front_controller = new FrontController($request, $settings, new Router, $logger);
$front_controller->route();
$front_controller->invoke();


Как видно, здесь я создаю необходимые FrontController'у объекты прямо в клиентском коде. Далее, в конструкторе, я прописываю их в свойства:

class FrontController
{
    private $request;
    private $settings;
    private $router;
    private $logger;
    private $controller;
    private $action;
    private $params = [];

    public function __construct(Request $request, Settings $settings, Router $router, Logger $logger)
    {
        $this->request = $request;
        $this->settings = $settings;
        $this->router = $router;
        $this->logger = $logger;
    }


И вот обратите внимание на new Router - он создаётся при создании FrontController, и более нигде в клиентском коде не используется. Как лучше: создавать его как в примере, или лучше убрать из аргументов и создавать в конструкторе:

public function __construct(Request $request, Settings $settings, Logger $logger)
    {
        $this->request = $request;
        $this->settings = $settings;
        $this->logger = $logger;

        $this->router = new Router;
    }


Никак не пойму, по какому принципу делается выбор между двумя этими вариантами...
  • Вопрос задан
  • 160 просмотров
Решения вопроса 1
iiifx
@iiifx
PHP, OOP, SOLID, Yii2, Composer, PHPStorm
Эммм... Контроллер создает роутер? Вам не кажется это странным?
На самом деле роутер должен создаваться ДО создания контроллера. То есть он сперва должен быть создан, инициализирован используя конфигурацию, после чего на основе указанных роутов и запроса определить какой именно был вызван и тогда лишь наступает очередь контроллера.

public function __construct(Request $request, Settings $settings, Router $router, Logger $logger)

Почему не используете тот же ServiceLocator?
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
riky
@riky
Laravel
пара вопросов на засыпку.
- кто уполномочен создавать роутер, сейчас он без параметров но потом может быть нужны будут параметры. например роутеру понадобится доступ к базе или банальный путь к файлу с роутами где они прописаны.

данный пример не очень показателен тк скорее всего у вас один бутстрап файл, один фронтконтроллер, и один роутер и к тому же один проект, либо проекты одинаковые. поэтому все изменения вы все равно сможете сделать в одном месте, либо в бутстрапе либо в конструкторе этом.

а представьте в другом проекте вам нужна будет другая реализация роутера? где вы будете вносить изменения?
правильно создать новый роутер, и передать в фронт контроллер из бутстрапа, тогда у вас будет потом не тронутый фронт контроллер, иначе если вы будете менять конструктор ФК то этот класс становится не переносимым.

очень рекомендую также использовать DI контейнер например из симфони
symfony.com/doc/current/components/dependency_inje...

тоже его в какой то момент начал использовать когда еще болел темой "я пишу свой фреймворк".
очень сложная это задача для новичка - сделать правильную архитектуру, хотя для самообучения это супер.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы