В последней части вы настроили класс контроллера и сгенерировали вывод с помощью echo. Но давайте не будем забывать, что у нас есть хорошая объектно-ориентированная абстракция HTTP. И сейчас она недоступна изнутри вашего класса.
Разумно будет воспользоваться инверсией управления. Т.е. вместо того, чтобы на класс возлагать ответственность за создание необходимого ему объекта, вы просто просите об этом. И делается это с помощью внедрения зависимостей. Если сейчас все звучит немного сложно, не волнуйтесь. Просто следуйте инструкциям, и, увидев конечную реализацию, многое станет понятно.
Измените контроллер Homepage таким образом:
<?php declare(strict_types = 1); namespace Example\Controllers; use Http\Response; class Homepage { private $response; public function __construct(Response $response) { $this->response = $response; } public function show() { $this->response->setContent('Hello World'); } }
Обратите внимание, что мы импортируем Http\Response наверху файла. Это означает, что всякий раз, когда вы используете Response внутри этого файла, он будет преобразован в полное имя (fully qualified name).
В конструкторе мы теперь явно запрашиваем Http\Response. В данном случае Http\Response — это интерфейс. Таким образом, можно внедрить любой класс, реализующий интерфейс. См. подсказки типов (type hinting) и интерфейсы для справки.
Пока код выдаст ошибку, поскольку на самом деле мы ничего еще не внедрили. Итак, давайте исправим это в Bootstrap.php, где мы осуществляем диспетчеризацию при распознании маршрута:
$class = new $className($response); $class->$method($vars);
Объект Http\HttpResponse реализует интерфейс Http\Response, поэтому он удовлетворяет нашему соглашению (контракту) и его можно использовать.
Теперь все снова должно работать. Но если вы последуете данному примеру, во все экземпляры ваших объектов, созданные таким образом, будут внедрены одни и те же объекты. Что, конечно, нехорошо, и мы исправим это в следующей части.