dongxingji3882 2016-07-25 21:44
浏览 25
已采纳

Zend Expressive - 注入中间件的最佳方式

I am currently learning zend expressive and I can see a couple of options as to how to access middleware within routes/actions.

In the expressive skeleton application, there is a HomePageFactory where the container is injected, then the router, template engine etc are pulled from the container and a new HomePageAction class is constructed using these and returned.

For example:

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

I then needed a flash messenger and came across the following:

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

So this is slightly different and is adding the middleware to the request via an attribute. Which can then be retrieved where its needed by something like:

$flashMessenger = $request->getAttribute('flash');

So really my question is what are the advantages/disadvantages of these two methods of getting the FlashMessenger into the action?

If I have a UserService which deals with retrieving users from a database and therefore may be needed in multiple actions/routes, would I be better off modifying the HomePageAction & Factory (and any others that need it) to accept the UserService?

i.e.

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

Or would I be better to go with how the FlashMessenger works (which seems a bit easier to manage) and add it to the request via an attribute to access it that way where needed?

i.e.

$userService = $request->getAttribute('UserService');

I'm wondering if there are any performance issues with the latter option, although I do understand that it could be done in this way only for specific routes rather than the UserServer being application wide.

My gut feeling (after writing out this question) is that really, this is a Service and not true middleware so I should really be Modifying the HomePageAction & Factory and adding the UserService that way rather than doing what seems easier and using the attribute ala FlashMessenger. But it would be very handy if a guru could help clarify this.

Many thanks in advance.

  • 写回答

1条回答 默认 最新

  • dongyou9373 2016-07-26 20:50
    关注

    I don't know about performance differences since I haven't tested this. But I guess the question you need to ask yourself is what does the class do? Is it needed by other middleware before or after invoking the Action class or do you need it only in the Action class or somewhere else in the application.

    In your case the UserService might take care of registering or updating an user. That stuff would be injected with the ActionFactory as your gut feeling tells you. However for authentication it would be different if that is done with middleware. First you need that class in your authentication middleware which you can pass on to your authorisation middleware with the request (or maybe only pass the authenticated user object, that's what I do).

    So I guess the rule of thumb is that if something is needed to change the incoming Request or outgoing Response before / after the Action, you pass it on with the Request, otherwise inject it in the Action with a Factory.

    If you start passing everything around with a Request, it will be very hard to keep track of. I find it much easier to inject as much as possible into the Action itself because then I can easily see what is needed inside that class and I can test it easier.

    Things like a flash messenger, session and the authenticated user I would inject in the request.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 matlab(相关搜索:紧聚焦)
  • ¥15 基于51单片机的厨房煤气泄露检测报警系统设计
  • ¥15 路易威登官网 里边的参数逆向
  • ¥15 Arduino无法同时连接多个hx711模块,如何解决?
  • ¥50 需求一个up主付费课程
  • ¥20 模型在y分布之外的数据上预测能力不好如何解决
  • ¥15 processing提取音乐节奏
  • ¥15 gg加速器加速游戏时,提示不是x86架构
  • ¥15 python按要求编写程序
  • ¥15 Python输入字符串转化为列表排序具体见图,严格按照输入