How can I get ServerRequestInterface with attributes in Factory?

expressive

#21

@matthew

Branding data are not request specific… Data are not derivated from request object. Those are pulled from external config file (which in my case is stored in /etc/imscp). Look my code above. The only thing that can change over the time is the year. But those data are layout scoped, not template scoped.


#22

It is, though, by virtue of being invoked within middleware. Neither middleware nor handlers should ever change the state of a service. Your middleware is doing exactly that, which means it is based on the current request state.

If this middleware will run on every request, then it’s better to add this information when creating the template renderer (e.g., via a delegator factory); default parameters are fine if they apply to every invocation of the renderer. If the parameters are only needed for request-specific piplelines or path-segregated pipelines, then you should be pushing that information into a request attribute and merging it with other data to render within your handler.

Again, please read the article I linked you to previously.


#23

I’ve read it full yesterday already :wink: I understand your point, hence my previous sentence where I say a thing like “you’ll surely say me it is best done in a factory”. The problem of setting those data through a factory is that the year will remain persisent with swoole.

I do not want annoy you, but I do think this is really an interesting topic :wink:


#24

You’re not changing state of a service through a pipeline middleware here?

Please don’t get me wrong… But I would really want understand when you can and when you cannot. If such thing above is valid, that mean I can also change state of Navigation service through pipeline middleware, that is, injecting a RouteResult and resetting state of the pages, no?

In the case above, you’re injecting a RouteResult which is based on the current request, right? What if a concurrent request make use of the UrlHelper at the same time (swoole context)?

Request A —> Inject RouteResult in UrlHeper
Request A —> Doing something…
Request B —> Inject RouteResult in UrlHeper
Request A —> UrlHepler->generate() using RouteResult from request B (OUCH)
Request B —> UrlHelper->generate() using RouteResult from request B (OK)


#25

Again, this is code that pre-dates much of our understanding of how state affects the sytem; it was part of the original v1 release, and has not changed substantially since then. We need to refactor/rewrite some of these various utilities to be stateless still.


#26

So you agreed that we have a big problem there (at least with swoole):

In the case above, you’re injecting a RouteResult which is based on the current request, right? What if a concurrent request make use of the UrlHelper at the same time (swoole context)?

Request A —> Inject RouteResult in UrlHeper
Request A —> Doing something…
Request B —> Inject RouteResult in UrlHeper
Request A —> UrlHepler->generate() using RouteResult from request B (OUCH)
Request B —> UrlHelper->generate() using RouteResult from request B (OK)

If yes, then, I understood your concerns. If not, I’m totally lost…

For me, that mostly means that swoole is currently a bad choice with zend expressive. The UrlHelper is really something important, isn’t it?


#27

Yes, this is exactly what I’ve been saying throughout this thread, multiple times.

I’m not saying that Swoole is a bad choice for Expressive, however. I’m saying you have to be careful which utilities you use, and when. There are a small handful of places we need to refactor to be stateless. As I noted previously, the HAL component’s metadata classees, and the template renderer (when using default parameters) are two of these; you’ve also identified the UrlHelper, which I’d thought about, but not really identified as problematic previously.

Why? Because it’s only a problem if you call it without arguments, and thus rely on the composed RouteResult. If you pass a route name and parameters to it, then it will not be a problem, as that usage does not rely on state. I’ll make a note to call this out in the documentation as well. (I tend to never call it without arguments; in zend-expressive-hal, we never do, either, making it safe.)


#28

Oh, and one other set of components: zend-validator and zend-inputfilter, as they retain state (specifically, failure messages). This is why we have a proposal for a stateless version.


#29

Of course, calling the helper with named route solve the issue :wink:

And view helpers too… I use them with Plates (with derivated renderer…) But ok… At least, a note in the documentation of these component or swoole components should be added.

Thank again.


#30

@matthew

Maybe a possible road… Implement a sandbox as it is done for Laravel swool component.