DI Container — правильный способ сделать это?

У меня есть длинный список инъекций зависимостей для отображения страницы со статьей, навигацией и т. Д. И в настоящее время я помещаю их в файл index.php, чтобы склеить их вместе.

index.php,

use MyCustomVerndorName\Constant\Mapper\ConstantsMapper;
use MyCustomVerndorName\Slug\Mapper\SlugMapper;
.... (more)

$ConstantService = new ConstantService();
$ConstantController = new ConstantController();

$ArticleService = new ArticleService();
$ArticleController = new ArticleController();

// Prepare Nav model.
$NavModel = new NavModel();
$NavMapper = new NavMapper($PdoAdapter);
$NavService->setMapper($NavMapper)->setModel($NavModel);

// Prepare Article model.
$ArticleModel = new ArticleModel();
$ArticleMapper = new ArticleMapper($PdoAdapter);

// Prepare components.
$ArticleContentComponent = new ArticleContentComponent($PdoAdapter);
... (more)

// Inject components.
$ArticleMapper->addComponent($ArticleContentComponent);
... (more)

$NavChildrenComponent = new NavChildrenComponent($PdoAdapter);
... (more)

// Inject components.
$NavMapper->addComponent($NavChildrenComponent);
$NavMapper->addComponent($NavLanguageComponent);

// Controll the slug.
$SlugController->setService($SlugService)->fetchRow([
"url"   =>  $url
]);

// Control the nav.
$NavController->setService($NavService)->fetchRows();

// Controll the article.
$ArticleService->setMapper($ArticleMapper)->setModel($ArticleModel);
$ArticleController->setService($ArticleService)->fetchRow([
"url"   =>  $url
]);

// Prepare template.
$PageTemplate = new PageTemplate();

// Prepare view.
$ArticleView = new ArticleView($PageTemplate, $ArticleModel);
$ArticleView->setSlug($SlugModel);
$ArticleView->setNav($NavModel);

// Render the view.
echo $ArticleView->render('index.php');

в моем router.php (я использую AltoRouter),

use AltoRouter as Router;

$Router = new Router();.
$Router->map('GET', '/', '/article/container');
... (and other routes)

if($match)
{
$target = $match['target'];
$url = isset($match['params']['url']) ? $match['params']['url'] : DEFAULT_HOMEPAGE;
$language = isset($match['params']['language']) ? $match['params']['language'] : null;

include __DIR__ . $target . '.php';

}

Я собираюсь сделать список инъекций зависимостей в index.php в контейнерный класс, чтобы я мог вызывать этот класс, когда это необходимо,

Для установки в router.php,

$Router->map('GET', '/', 'MyCustomVerndorName\Article\Container\ArticleContainer');
....
new $target($PdoAdapter, $url, $language);

И этот контейнерный класс,

namespace MyCustomVerndorName\Article\Container;

// Mapper.
use MyCustomVerndorName\Constant\Mapper\ConstantsMapper;
...

class ArticleContainer
{

/*
* Construct dependency.
*/
public function __construct(\MyCustomVerndorName\Adapter\PdoAdapter $PdoAdapter, $url, $language)
{
$ConstantService = new ConstantService();
$ConstantController = new ConstantController();

// Slug.
$SlugService = new SlugService();
$SlugController = new SlugController();

// Nav.
$NavService = new NavService();
$NavController = new NavController();

// Article.
$ArticleService = new ArticleService();
$ArticleController = new ArticleController();

// Prepare Article model.
$ArticleModel = new ArticleModel();
$ArticleMapper = new ArticleMapper($PdoAdapter);

// Prepare components.
$ArticleContentComponent = new ArticleContentComponent($PdoAdapter);
...

// Inject components.
$ArticleMapper->addComponent($ArticleContentComponent);
...

// Control the nav.
$NavController->setService($NavService)->fetchRows();

// Controll the article.
$ArticleService->setMapper($ArticleMapper)->setModel($ArticleModel);
$ArticleController->setService($ArticleService)->fetchRow([
"url"   =>  $url
]);// Prepare template.
$PageTemplate = new PageTemplate();

// Prepare view.
$ArticleView = new ArticleView($PageTemplate, $ArticleModel);
$ArticleView->setSlug($SlugModel);
$ArticleView->setNav($NavModel);

// Render the view.
echo $ArticleView->render('index.php');
}
}

В основном, я положил весь список зависимостей в __construct,

public function __construct(\MyCustomVerndorName\Adapter\PdoAdapter $PdoAdapter, $url, $language)
{
...
}

Итак, это правильный способ сделать DI-контейнер, не опирающийся на хорошо известные контейнеры для PHP (такие как Pimple, Symfony \ DependencyInjection и т. д.)?

0

Решение

Традиционно DI-контейнер возвращает услуги по требованию. То, что вы называете ArticleContainer, на самом деле является просто функцией, которая затем отображает представление. Он делает много DI-инъекций, но это не контейнер.

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

$container = new Container();

// Some initialization

// Now use it
$viewArticle = $container->get('view_article');
echo $viewArticle->render('index.php');

Надеюсь, вы увидите разницу. После завершения инициализации ваше приложение просто извлекает необходимое представление и отображает его. Не нужно беспокоиться о pdo или url и т. Д.

Итак, как мы можем получить наш сервис просмотра статей в контейнер?

$container = new Container();

// Some initialization
$container->set('page_template',function($container)
{
return new PageTemplate();
}
$container->set('article_view',function($container)
{
$articleView = new ArticleView(
$container->get('page_template',
$container->get('article_model')
);
$articleView->setSlug($container->get('slug_model');
$articleView->setNav ($container->get('nav_model');

return $articleView;
};
// Now use it
$viewArticle = $container->get('article_view');
echo $viewArticle->render('index.php');

Итак, мы определили две сервисные функции для нашего контейнера. Когда мы делаем $ container-> get (‘article_view’);; контейнер вызывает функцию с самим контейнером в качестве аргумента. Функция создает нужный класс, вытаскивая зависимости из контейнера, а затем возвращает новый объект.

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

Вы просто продолжаете добавлять сервисы в контейнер.

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

1

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

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

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