You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Today, I was bitten by the denormalization of URI query-strings between the URI model and the ServerRequest model.
I was delegating a request object, and although the URI included a set of query params, these did not propagate from the URI model to the ServerRequest model - and the consumer component happened to be getting this information from the ServerRequest model rather than from the URI model, and so of course this turned into somewhat of a nightmare of debugging and tracing.
Note: the query params might not be in sync with the URI or server
params. If you need to ensure you are only getting the original
values, you may need to parse the query string from getUri()->getQuery()
or from the QUERY_STRING server param.
Note the precise phrasing: it might not be in sync with the URI model.
IMO, it's extremely problematic that PSR-7 was designed with a built-in denormalization issue, and since the specification seems to imply that implementations might (may) keep these values in sync, I strongly suggest we do that.
Now, I understand that these two models are, strictly speaking, incompatible - because the query string is just a string, and doesn't have to follow the common a=1&b=2 query format, and as such, you can't simply make this data synchronize in both directions.
However, this is still denormalization, and it still causes problems - having to update both values with two representations of the same data basically guarantees inconsistency, which basically guarantees (eventually) bugs.
Since the query string is the most general representation of the query data, I'd suggest treating the query-params in the ServerRequest as an accessor for the query-string inside the URI model.
You can of course still denormalize the query data internally (for performance) but it should behave as though the query-string is one value.
The elephant in the room of course is this: what happens if I ask the ServerRequest model for the query params, and the query-string in the underlying URI model isn't something that can be decoded as query params?
I suspect this question is what lead to apparent overthinking in the design of PSR-7, and I think that one possible answer to that question is actually much simpler than you may be thinking. The answer lies in PHP itself. What does PHP do if you provide a query-string it can't decode? Simple answer: nothing.
While this may seem "wrong" on the surface, it's actually completely appropriate - the $_GET superglobal, just like the ServerRequest::getQueryParams() method I'm proposing, provides an API that lets you access correctly encoded query parameters extracted from the query string, only if such paramters are present.
If you think of it that way, if there is an underlying query string in the URI model that doesn't contain such encoded parameters, that's precisely what you'd expect to be able to access: an empty array. If you wanted (or wanted to manipulate) the actual query-string, you'd ask the URI model for that.
I don't believe there's any real disconnect there at all; and it's consistent with PHP's own behavior, and therefore shouldn't really be surprising at all.
As things stand, the model doesn't actually make any sense - what we're dealing with is two representations of the same value, not two different values. The way it's modeled right now, the model actually permits the same property to have two different values at the same time.
I'm sure that makes a bunch of sense to people who understand quantum mechanics, but that's probably not most of us ;-)
The bottom line is that these are two different representations of the query string portion of the request URI, not two different values.
By the way, the same issues exists for post-variables and the body stream - and again, consistent with PHP, a body that does not represent post-variables in the expected format can simply be treated as empty, since the accessors are for post-variables in the expected format, not for other arbitrary post-data, e.g. consistent with $_POST.
Today, I was bitten by the denormalization of URI query-strings between the URI model and the ServerRequest model.
I was delegating a request object, and although the URI included a set of query params, these did not propagate from the URI model to the ServerRequest model - and the consumer component happened to be getting this information from the ServerRequest model rather than from the URI model, and so of course this turned into somewhat of a nightmare of debugging and tracing.
Per the relevant doc-block PSR-7, this denormalization may be expected:
Note the precise phrasing: it might not be in sync with the URI model.
IMO, it's extremely problematic that PSR-7 was designed with a built-in denormalization issue, and since the specification seems to imply that implementations might (may) keep these values in sync, I strongly suggest we do that.
Now, I understand that these two models are, strictly speaking, incompatible - because the query string is just a string, and doesn't have to follow the common
a=1&b=2
query format, and as such, you can't simply make this data synchronize in both directions.However, this is still denormalization, and it still causes problems - having to update both values with two representations of the same data basically guarantees inconsistency, which basically guarantees (eventually) bugs.
Since the query string is the most general representation of the query data, I'd suggest treating the query-params in the ServerRequest as an accessor for the query-string inside the URI model.
You can of course still denormalize the query data internally (for performance) but it should behave as though the query-string is one value.
The elephant in the room of course is this: what happens if I ask the ServerRequest model for the query params, and the query-string in the underlying URI model isn't something that can be decoded as query params?
I suspect this question is what lead to apparent overthinking in the design of PSR-7, and I think that one possible answer to that question is actually much simpler than you may be thinking. The answer lies in PHP itself. What does PHP do if you provide a query-string it can't decode? Simple answer: nothing.
While this may seem "wrong" on the surface, it's actually completely appropriate - the
$_GET
superglobal, just like theServerRequest::getQueryParams()
method I'm proposing, provides an API that lets you access correctly encoded query parameters extracted from the query string, only if such paramters are present.If you think of it that way, if there is an underlying query string in the URI model that doesn't contain such encoded parameters, that's precisely what you'd expect to be able to access: an empty array. If you wanted (or wanted to manipulate) the actual query-string, you'd ask the URI model for that.
I don't believe there's any real disconnect there at all; and it's consistent with PHP's own behavior, and therefore shouldn't really be surprising at all.
As things stand, the model doesn't actually make any sense - what we're dealing with is two representations of the same value, not two different values. The way it's modeled right now, the model actually permits the same property to have two different values at the same time.
I'm sure that makes a bunch of sense to people who understand quantum mechanics, but that's probably not most of us ;-)
The bottom line is that these are two different representations of the query string portion of the request URI, not two different values.
Would you be open to changing this?
Originally posted by @mindplay-dk at zendframework/zend-diactoros#184
The text was updated successfully, but these errors were encountered: