PHP MVC DI практический пример закона Деметры с маршрутизатором, контроллером и моделью

Борьба с MVC в PHP.
Мои опасения выросли еще больше после просмотра этого:
https://www.youtube.com/watch?v=RlfLCWKxHJ0

Согласно LoD мой класс Router должен знать только Request Uri для загрузки соответствующего класса Controller. Однако мой Контроллер должен знать, какой класс Model он должен использовать, и класс View для представления данных. Или, лучше, Controller должен знать ModelFactory, который будет обрабатывать создание объектов с использованием выбранного хранилища данных.

Это все ломает LoD для меня.

Итак, мой вопрос:

  1. Как маршрутизатор должен инициализировать класс контроллера, не зная, какой
    параметры это нужно? Даже если это DI-контейнер, мы не знаем
    параметры объекта для передачи конструктору внутри маршрутизатора. Если мы передадим DI-контейнер конструктору Router (или любому другому классу), мы вернемся к Service Locator. Как это должно быть сделано?

Может быть, это все неправильно, но моя отправная точка:

// ... retrieve settings, available languages, start session,...

$router     = new Router($settings);
$router->loadController();

router.php

class Router
{
public function __construct(Settings $settings)
{
$this->settings = $settings;
}

// some other methods

public function loadController()
{
try
{
// Loading controller
$controller = $this->getController();

if (is_callable(array($controller, $this->method)) == false)
$this->method = 'init';

// Running controller
$controller->{$this->method}();
}
catch (Exception $e)
{
$e->displayMessage();
}
}
}

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

Больше вопросов:

  1. Как мне получить экземпляр класса Model в контроллере? Должен ли я использовать статический метод для загрузки View?

2

Решение

Во-первых, модель представляет собой слой, а не определенный класс. Контроллер сам инициирует классы, необходимые для начала обработки бизнес-логики вашего приложения.

Посмотрите на эти ответы. 2-й имеет несколько примеров того, как эти классы можно назвать …

Как модель должна быть структурирована в MVC?

Правильно ли вызывать базу данных из Model в приложении MVC?

Во-вторых, маршрутизатор просто направляет запрошенную ссылку на определенный контроллер и просматривает. Есть разные способы сделать это, но мой маршрутизатор (ы) проверяет совпадения с существующей картой ресурсов. Основываясь на нескольких других вещах, он либо вернет успешное имя «ресурса» для страницы, имя ресурса для страниц, которые не найдены, либо ресурс для перенаправления и т. Д.

Некоторый базовый код из начальной загрузки для иллюстрации …

//snip

$routeLoader = new \Routing\RouteLoader();
$match = $routeLoader->getMatchedRoute( $request['pageName'] );

$router = new \Routing\Router( $request );
$resource = $router->getResource( $match );

//snip

$viewName       = '\View\\' . $resource . 'View';
$controllerName = '\Controller\\' . $resource . 'Controller';

$view = new $viewName();
$controller = new $controllerName( $view, $request );
$controller->{$router->getCommand()}();

$view->response();

Итак, чтобы прямо ответить на ваши вопросы ..

1) Не запускайте контроллер и не просматривайте класс маршрутизатора. Сделай это в начальной загрузке.

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

2) Контроллер инициирует классы, чтобы начать обработку бизнес-логики (если это даже необходимо.)

ДОПОЛНИТЕЛЬНЫЙ

Чтобы добавить соединение с базой данных к вышеуказанному и вставить его в контроллер, ниже приведен 1 способ сделать это.

$DCM = new \Database\DatabaseConnectionManager( new \Config\DatabaseConfig() );
$AppCache = new \Cache\AppCache();
$DAM = new \DataAccess\DataAccessManager( $AppCache, $DCM );

В приведенном выше коде объект DataAccessManager будет отвечать за извлечение данных либо из первого кэша, либо второго из базы данных. Этот объект $ DAM теперь может быть введен в контроллер, вот так …

$controller = new $controllerName( $DAM, $view, $request );

Вместо того, чтобы подключаться к базе данных в начальной загрузке и передавать соединение вокруг приложения, я предпочитаю использовать DataAccessManager, который будет устанавливать соединение только тогда, когда это действительно необходимо. Как только это необходимо, объект PDO (или любой другой объект) инициируется и сохраняется в объекте, который необходимо извлечь и использовать снова, если это необходимо. Я также могу подключиться к другим базам данных, если это необходимо ..

// method from DataAccessManager class

private function connectToDatabase( $server = 'slave' )
{
if (!array_key_exists( $server, $this->dbObject )) {
// use the DataConnectionManager to connect and store the connection here
$this->dbObject[$server] = $this->DCM->connect( $server );
}

return $this->dbObject[$server];
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]