我正在启动一个新的slim 4应用程序,当前的slim版本更多的是路由器而不是框架,并且没有开箱即用的di容器,因此我选择PHP-DI
作为DI容器。为了不描述容器中的每个控制器,并且不将容器实例传递给我正在使用PHP-DI
自动装配的控制器。
但是使用这种方法,我需要将所有依赖项注入到每个控制器中,并且大多数依赖项可以被所有控制器重用。示例:
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
http://php-di.org/doc/best-practices.html#writing-controllers建议使用属性注入,但是对于每个控制器注入所有可重复使用的注入,这看起来仍然像是一个样板,当我们注入私有属性时,它破坏了封装。
我可以想到的解决方案之一是用所有可重用的依赖项来制作某种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
答案 0 :(得分:0)
你可以尝试像下面的“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;
}
}
然后当你调用你的控制器时,你可以这样做:
<?php
namespace App\Controller\Auth;
use App\Application\Controller;
class AuthController extends BaseController
{
public function showLogin()
{
return $this->view('auth/login.html');
}
}