Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/255.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何用PHPDI正确注入可重用控制器注入_Php_Dependency Injection_Controller_Php Di - Fatal编程技术网

如何用PHPDI正确注入可重用控制器注入

如何用PHPDI正确注入可重用控制器注入,php,dependency-injection,controller,php-di,Php,Dependency Injection,Controller,Php Di,我正在启动一个新的slim 4应用程序,当前的slim版本更像是一个路由器而不是一个框架,没有现成的di容器,因此我选择PHP-di作为di容器。为了不描述容器中的每个控制器,也为了不将容器实例传递给控制器,我正在使用PHP-DIautowiring 但是使用这种方法,我需要将所有依赖项注入到每个控制器中,并且这些依赖项中的大多数都可以被所有控制器重用。例如: public function __construct( Environment $twig, Messages $fl

我正在启动一个新的slim 4应用程序,当前的slim版本更像是一个路由器而不是一个框架,没有现成的di容器,因此我选择
PHP-di
作为di容器。为了不描述容器中的每个控制器,也为了不将容器实例传递给控制器,我正在使用
PHP-DI
autowiring

但是使用这种方法,我需要将所有依赖项注入到每个控制器中,并且这些依赖项中的大多数都可以被所有控制器重用。例如:

public function __construct(
    Environment $twig,
    Messages $flashMessage,
    RouteCollectorInterface $routeCollector
)
{
    $this->render = $twig;
    $this->flashMessage = $flashMessage;
    $this->routeCollector = $routeCollector;
}
有没有办法制作一个基本控制器,向其注入所有可重用的依赖项,以便在
DIc
创建/自动连接每个新控制器时,所有已注入的依赖项b-z控制器扩展基本控制器?此外,基本控制器可能应该使用方法注入,否则,我仍然需要创建一个构造函数,并将每个控制器中的所有注入传递给基本控制器,如下所示:

public function __construct(
    Environment $twig,
    CommandBus $commandBus,
    Messages $flashMessage,
    RouteCollectorInterface $routeCollector
)
{
     parent::__construct($twig, $flashMessage, $routeCollector);
    $this->commandBus = $commandBus;
}
这可能与在没有基本controlelr的情况下向每个控制器注入依赖项是一样的

我尝试配置基本控制器:

   $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
建议使用属性注入,但对我来说,为每个控制器注入所有可重用的注入仍然像一个样板,当我们注入私有属性时,它破坏了封装

我能想到的一个解决方案是使用所有可重用的依赖项作为桥接器/包装器来创建某种
ControllerHelper
,并将其注入,而不是所有这些依赖项,这将减少重复代码的数量。但是,也许还有更好的解决办法

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

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

 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
类方法,它使用模板引擎依赖项来呈现视图:

public function render(ResponseInterface $request, string $templateName, array $data): ResponseInterface {
          $response->getBody()->write(
            $this->render->render(
                $templateName,
                $data
            )
        );

        return $response;
}

如您所见,我不想将依赖项注入
SomeController
,而是以某种方式将它们注入
BaseController

您可以尝试像以下“BaseController”控制器类那样执行此操作:

<?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;
    }
}

您可以尝试像以下“BaseController”控制器类那样执行此操作:

<?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;
    }
}