简体   繁体   English

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

[英]Zend Expressive - Best way to inject middleware

I am currently learning zend expressive and I can see a couple of options as to how to access middleware within routes/actions. 我目前正在学习zend表现力,我可以看到一些关于如何在路线/动作中访问中间件的选择。

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. 在具有表现力的骨架应用程序中,有一个HomePageFactory,在其中注入了容器,然后从容器中拉出了路由器,模板引擎等,并使用这些容器构造了一个新的HomePageAction类并返回了该类。

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: 然后,我需要一个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
            );
        };
    }
}

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? 所以,实际上我的问题是,这两种使FlashMessenger付诸实践的方法的优点/缺点是什么?

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? 如果我有一个UserService可以处理从数据库中检索用户的问题,因此可能需要在多个操作/路由中进行修改,那么最好修改HomePageAction&Factory(以及需要它的任何其他对象)以接受UserService吗?

ie

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? 还是我会更好地考虑FlashMessenger的工作方式(似乎更易于管理),然后通过属性将其添加到请求中,以便在需要时以这种方式访问​​它?

ie

$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. 我想知道后一个选项是否存在任何性能问题,尽管我确实知道只能以这种方式针对特定的路由而不是整个应用程序范围内的UserServer来完成。

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. 我的直觉(写完这个问题之后)是,这真的是服务,而不是真正的中间件,因此,我应该真的是在修改HomePageAction和Factory并以这种方式添加UserService,而不是做看起来更轻松的事情并使用属性ala FlashMessenger 。 But it would be very handy if a guru could help clarify this. 但是,如果一个专家可以帮助澄清这一点,将非常方便。

Many thanks in advance. 提前谢谢了。

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. 在调用Action类之前或之后,其他中间件是否需要它?还是仅在Action类中或应用程序中的其他地方需要它?

In your case the UserService might take care of registering or updating an user. 在您的情况下,UserService可能会负责注册或更新用户。 That stuff would be injected with the ActionFactory as your gut feeling tells you. 当您的直觉告诉您时,会将这些东西注入ActionFactory中。 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. 我发现将尽可能多的内容注入Action本身要容易得多,因为这样我就可以轻松地看到该类内部需要什么,并且可以对其进行更轻松的测试。

Things like a flash messenger, session and the authenticated user I would inject in the request. 我会在请求中注入Flash Messenger,会话和经过身份验证的用户之类的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM