首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何正确注入具有php-di的可重用控制器注入

如何正确注入具有php-di的可重用控制器注入
EN

Stack Overflow用户
提问于 2019-12-17 09:32:55
回答 1查看 523关注 0票数 2

我正在启动一个新的slim 4应用程序,而当前的slim版本更多的是一个路由器而不是一个框架,并且没有公开的di容器,所以我选择PHP-DI作为一个DI容器。为了不描述容器中的每个控制器,也为了不将容器实例传递给控制器,我使用了PHP-DI自动装配。

但是,使用这种方法,我需要向每个控制器注入所有依赖项,并且所有控制器都可以重用这些依赖项。示例:

代码语言:javascript
复制
public function __construct(
    Environment $twig,
    Messages $flashMessage,
    RouteCollectorInterface $routeCollector
)
{
    $this->render = $twig;
    $this->flashMessage = $flashMessage;
    $this->routeCollector = $routeCollector;
}

是否有一种方法可以创建一个基本控制器,将所有可重用的依赖项注入到它,以便当DIc创建/自动更新每个新控制器时,所有已注入的依赖项都扩展为基本依赖项?此外,基本控制器可能应该使用方法注入,否则,我仍然需要创建一个构造函数,并将每个控制器中的所有注入传递给基本控制器,如下所示:

代码语言:javascript
复制
public function __construct(
    Environment $twig,
    CommandBus $commandBus,
    Messages $flashMessage,
    RouteCollectorInterface $routeCollector
)
{
     parent::__construct($twig, $flashMessage, $routeCollector);
    $this->commandBus = $commandBus;
}

这可能与将依赖项注入到每个控制器而不使用基本控件的情况相同。

我试图配置contoller基地:

代码语言:javascript
复制
   $definitions[BaseController::class] = static function(ContainerInterface $container): BaseController {
        /** @var BaseController $controller */
        $controller =new BaseController();
        $controller->setView($container->get(Environment::class));
        $controller->setRouter($container->get(RouteCollectorInterface::class));
        $controller->setFleshMessage($container->get(Messages::class));

        return $controller;
    };

但是它不起作用,对于每个扩展基本控制器的控制器,依赖项都是null

PHP-DI http://php-di.org/doc/best-practices.html#writing-controllers建议使用属性注入,但对于我来说,为每个控制器注入所有可重用的注入仍然是一个样板,而且当我们注入私有属性时,它正在破坏封装。

我能想到的解决方案之一是用所有可重用的依赖项作为桥接/包装器,并将其注入ControllerHelper,而不是所有的依赖项,这样可以减少重复代码的数量。但是,也许还有更好的解决方案?

更新:我知道它实际上是如何在OOP中工作的,如果扩展基类,需要将所有依赖项传递给它。但是为了减少一些重复,一些魔法在这里是很好的:)而且它也不是一个将被其他人使用的外部程序包,所以如果有可能实现的话,这种魔法很可能是可以的。

更新:,换句话说,我想要实现的是:

代码语言:javascript
复制
 class SomeController extends BaseController {
// in this case constructor is empty 

        public function index(RequestInterface $request, ResponseInterface $response) {
             return $this->render($response, $templateName, [somedata]);
        }
    }

其中$this-render是一个BaseController类方法,它使用模板引擎依赖来呈现视图:

代码语言:javascript
复制
public function render(ResponseInterface $request, string $templateName, array $data): ResponseInterface {
          $response->getBody()->write(
            $this->render->render(
                $templateName,
                $data
            )
        );

        return $response;
}

如您所见,我不想将依赖项注入到SomeController,而是将它们注入BaseController一次。

EN

回答 1

Stack Overflow用户

发布于 2021-05-30 03:49:44

您可以尝试类似于下面的"BaseController“控制器类:

代码语言:javascript
复制
<?php

namespace App\Application;

use Twig\Environment;
use Laminas\Diactoros\Response;
use Psr\Http\Message\ResponseInterface;

abstract class BaseController
{
    private $template;

    public function __construct(Environment $template)
    {
        $this->template = $template;
    }

    public function view(string $template, array $data = []) : ResponseInterface
    {
        $result = $this->template->render($template, $data);

        $response = new Response();
        $response->getBody()->write($result);
        return $response;
    }
}

然后,当调用控制器时,您可以这样做:

代码语言:javascript
复制
<?php

namespace App\Controller\Auth;

use App\Application\Controller;

class AuthController extends BaseController
{

    public function showLogin()
    {
        return $this->view('auth/login.html');
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59371248

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档