В последней части вы настроили класс контроллера и сгенерировали вывод с помощью 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, поэтому он удовлетворяет нашему соглашению (контракту) и его можно использовать.

Теперь все снова должно работать. Но если вы последуете данному примеру, во все экземпляры ваших объектов, созданные таким образом, будут внедрены одни и те же объекты. Что, конечно, нехорошо, и мы исправим это в следующей части.

Источник

Наверх