Zend Expressive - 注入中间件的最佳方式
Zend Expressive - Best way to inject middleware
我目前正在学习 zend expressive,我可以看到几个关于如何在 routes/actions 中访问中间件的选项。
在富有表现力的骨架应用程序中,有一个 HomePageFactory,其中注入了容器,然后从容器中提取路由器、模板引擎等,并使用这些构造并返回一个新的 HomePageAction class。
例如:
class HomePageFactory
{
public function __invoke(ContainerInterface $container)
{
$router = $container->get(RouterInterface::class);
$template = ($container->has(TemplateRendererInterface::class))
? $container->get(TemplateRendererInterface::class)
: null;
return new HomePageAction($router, $template);
}
然后我需要一个 flash messenger 并遇到了以下内容:
class SlimFlashMiddlewareFactory
{
public function __invoke($container)
{
return function ($request, $response, $next) {
// Start the session whenever we use this!
session_start();
return $next(
$request->withAttribute('flash', new Messages()),
$response
);
};
}
}
所以这略有不同,是通过属性将中间件添加到请求中。然后可以通过以下方式在需要的地方检索它:
$flashMessenger = $request->getAttribute('flash');
所以我的问题真的是 advantages/disadvantages 这两种让 FlashMessenger 起作用的方法是什么?
如果我有一个处理从数据库中检索用户的 UserService,因此可能需要多个 actions/routes,我是否最好修改 HomePageAction & Factory(以及任何其他需要它的)以接受 UserService?
即
class HomePageFactory
{
public function __invoke(ContainerInterface $container)
{
$router = $container->get(RouterInterface::class);
$template = ($container->has(TemplateRendererInterface::class))
? $container->get(TemplateRendererInterface::class)
: null;
$userService = $container->get(App\UserService::class);
return new HomePageAction($router, $template, $userService);
}
或者我会更好地了解 FlashMessenger 的工作方式(这似乎更易于管理)并通过属性将其添加到请求中以在需要时以这种方式访问它?
即
$userService = $request->getAttribute('UserService');
我想知道后一个选项是否存在任何性能问题,尽管我知道它可以只针对特定路由而不是 UserServer 在应用程序范围内以这种方式完成。
我的直觉(在写完这个问题之后)是,这真的是一个服务,而不是真正的中间件,所以我真的应该修改 HomePageAction & Factory 并以这种方式添加 UserService,而不是做看起来更容易和更容易的事情使用属性 ala FlashMessenger。但是,如果有大师可以帮助澄清这一点,那将非常方便。
非常感谢。
我不知道性能差异,因为我还没有测试过。但我想您需要问自己的问题是 class 的作用是什么?在调用 Action class 之前或之后其他中间件是否需要它,或者您只在 Action class 或应用程序中的其他地方需要它。
在您的情况下,UserService 可能负责注册或更新用户。正如您的直觉告诉您的那样,这些东西将通过 ActionFactory 注入。但是对于身份验证,如果使用中间件完成,情况会有所不同。首先,您需要在您的身份验证中间件中使用 class,您可以通过请求将其传递给您的授权中间件(或者可能只传递经过身份验证的用户对象,这就是我所做的)。
所以我猜经验法则是,如果需要在操作之前/之后更改传入请求或传出响应,则将其与请求一起传递,否则将其注入到带有工厂的操作中。
如果您开始使用请求传递所有内容,将很难跟踪。我发现尽可能多地注入 Action 本身要容易得多,因为这样我就可以很容易地看到里面需要什么 class 并且我可以更容易地测试它。
诸如 flash messenger、会话和经过身份验证的用户之类的东西,我会在请求中注入。
我目前正在学习 zend expressive,我可以看到几个关于如何在 routes/actions 中访问中间件的选项。
在富有表现力的骨架应用程序中,有一个 HomePageFactory,其中注入了容器,然后从容器中提取路由器、模板引擎等,并使用这些构造并返回一个新的 HomePageAction class。
例如:
class HomePageFactory
{
public function __invoke(ContainerInterface $container)
{
$router = $container->get(RouterInterface::class);
$template = ($container->has(TemplateRendererInterface::class))
? $container->get(TemplateRendererInterface::class)
: null;
return new HomePageAction($router, $template);
}
然后我需要一个 flash messenger 并遇到了以下内容:
class SlimFlashMiddlewareFactory
{
public function __invoke($container)
{
return function ($request, $response, $next) {
// Start the session whenever we use this!
session_start();
return $next(
$request->withAttribute('flash', new Messages()),
$response
);
};
}
}
所以这略有不同,是通过属性将中间件添加到请求中。然后可以通过以下方式在需要的地方检索它:
$flashMessenger = $request->getAttribute('flash');
所以我的问题真的是 advantages/disadvantages 这两种让 FlashMessenger 起作用的方法是什么?
如果我有一个处理从数据库中检索用户的 UserService,因此可能需要多个 actions/routes,我是否最好修改 HomePageAction & Factory(以及任何其他需要它的)以接受 UserService?
即
class HomePageFactory
{
public function __invoke(ContainerInterface $container)
{
$router = $container->get(RouterInterface::class);
$template = ($container->has(TemplateRendererInterface::class))
? $container->get(TemplateRendererInterface::class)
: null;
$userService = $container->get(App\UserService::class);
return new HomePageAction($router, $template, $userService);
}
或者我会更好地了解 FlashMessenger 的工作方式(这似乎更易于管理)并通过属性将其添加到请求中以在需要时以这种方式访问它?
即
$userService = $request->getAttribute('UserService');
我想知道后一个选项是否存在任何性能问题,尽管我知道它可以只针对特定路由而不是 UserServer 在应用程序范围内以这种方式完成。
我的直觉(在写完这个问题之后)是,这真的是一个服务,而不是真正的中间件,所以我真的应该修改 HomePageAction & Factory 并以这种方式添加 UserService,而不是做看起来更容易和更容易的事情使用属性 ala FlashMessenger。但是,如果有大师可以帮助澄清这一点,那将非常方便。
非常感谢。
我不知道性能差异,因为我还没有测试过。但我想您需要问自己的问题是 class 的作用是什么?在调用 Action class 之前或之后其他中间件是否需要它,或者您只在 Action class 或应用程序中的其他地方需要它。
在您的情况下,UserService 可能负责注册或更新用户。正如您的直觉告诉您的那样,这些东西将通过 ActionFactory 注入。但是对于身份验证,如果使用中间件完成,情况会有所不同。首先,您需要在您的身份验证中间件中使用 class,您可以通过请求将其传递给您的授权中间件(或者可能只传递经过身份验证的用户对象,这就是我所做的)。
所以我猜经验法则是,如果需要在操作之前/之后更改传入请求或传出响应,则将其与请求一起传递,否则将其注入到带有工厂的操作中。
如果您开始使用请求传递所有内容,将很难跟踪。我发现尽可能多地注入 Action 本身要容易得多,因为这样我就可以很容易地看到里面需要什么 class 并且我可以更容易地测试它。
诸如 flash messenger、会话和经过身份验证的用户之类的东西,我会在请求中注入。