Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

This is only part of a thread. view whole thread
  108581
February 14, 2020 15:47 pmjones@pmjones.io ("Paul M. Jones")
Hi Côme & Niklas,

> On Feb 13, 2020, at 04:52, Côme Chilliet chilliet@fusiondirectory.org> wrote: > > Le mercredi 12 février 2020, 19:20:56 CET Niklas Keller a écrit : > >> Naming >> >> I think we shouldn't take over the naming of the super globals, e.g. >> $_GET really contains the query parameters and has nothing to do with >> GET or POST, so $request->getQueryParameter(...) would be a better >> name. > > I think this remark is really on point. > GET and POST are HTTP methods and not ways of passing data. You can have query parameters on any request, and you can have POST data with a lot of other HTTP methods, as is commonly used in REST APIs.
Your comments on naming are well-made. While working on the implementation, we tried out $query instead of $get, on exactly the premise that you state: i.e., that `$_GET` holds the query parameters, and has nothing to do with the GET method. But in the end, we settled on mapping more directly from `$_GET` => `$get`, and `$_POST => $post`. Having said that, we are willing to revisit that naming decision if there's support for doing so. Perhaps: - rename $get to $query, populating it from `$globals['_GET']`, on the basis stated above - rename $post to $input, populating it from `$globals['_POST']`, on the basis that it typically relates to the parsed form of php://input Your (and/or anyone else's) thoughts on that? -- Paul M. Jones pmjones@pmjones.io http://paul-m-jones.com Modernizing Legacy Applications in PHP https://leanpub.com/mlaphp Solving the N+1 Problem in PHP https://leanpub.com/sn1php
  108582
February 14, 2020 16:03 benjamin.morel@gmail.com (Benjamin Morel)
> > Having said that, we are willing to revisit that naming decision if > there's support for doing so. Perhaps: > - rename $get to $query, populating it from `$globals['_GET']`, on the > basis stated above > - rename $post to $input, populating it from `$globals['_POST']`, on the > basis that it typically relates to the parsed form of php://input > Your (and/or anyone else's) thoughts on that?
Symfony uses $request->query and $request->request for $_GET and $_POST, respectively. I like $request->query for query params, but always found $request->request for body parameters confusing. I like $request->input a bit better, although I'd be interested to hear more ideas on this one. — Benjamin On Fri, 14 Feb 2020 at 16:47, Paul M. Jones <pmjones@pmjones.io> wrote:
> Hi Côme & Niklas, > > > On Feb 13, 2020, at 04:52, Côme Chilliet < > come.chilliet@fusiondirectory.org> wrote: > > > > Le mercredi 12 février 2020, 19:20:56 CET Niklas Keller a écrit : > > > >> Naming > >> > >> I think we shouldn't take over the naming of the super globals, e.g. > >> $_GET really contains the query parameters and has nothing to do with > >> GET or POST, so $request->getQueryParameter(...) would be a better > >> name. > > > > I think this remark is really on point. > > GET and POST are HTTP methods and not ways of passing data. You can have > query parameters on any request, and you can have POST data with a lot of > other HTTP methods, as is commonly used in REST APIs. > > Your comments on naming are well-made. > > While working on the implementation, we tried out $query instead of $get, > on exactly the premise that you state: i.e., that `$_GET` holds the query > parameters, and has nothing to do with the GET method. But in the end, we > settled on mapping more directly from `$_GET` => `$get`, and `$_POST => > $post`. > > Having said that, we are willing to revisit that naming decision if > there's support for doing so. Perhaps: > > - rename $get to $query, populating it from `$globals['_GET']`, on the > basis stated above > - rename $post to $input, populating it from `$globals['_POST']`, on the > basis that it typically relates to the parsed form of php://input > > Your (and/or anyone else's) thoughts on that? > > > -- > Paul M. Jones > pmjones@pmjones.io > http://paul-m-jones.com > > Modernizing Legacy Applications in PHP > https://leanpub.com/mlaphp > > Solving the N+1 Problem in PHP > https://leanpub.com/sn1php > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
  108584
February 14, 2020 16:44 weirdan@gmail.com (Bruce Weirdan)
On Fri, Feb 14, 2020 at 5:47 PM Paul M. Jones <pmjones@pmjones.io> wrote:
>
> - rename $get to $query, populating it from `$globals['_GET']`, on the basis stated above > - rename $post to $input, populating it from `$globals['_POST']`, on the basis that it typically relates to the parsed form of php://input
What about $query and $body? That would be closer to the terminology used in HTTP RFCs. -- Best regards, Bruce Weirdan mailto:weirdan@gmail.com
  108585
February 14, 2020 16:47 benjamin.morel@gmail.com (Benjamin Morel)
> > What about $query and $body? That would be closer to the terminology > used in HTTP RFCs.
The problem is that $body is typically used to get the raw message body as a string or stream. I was thinking more something along the lines of $bodyParams, which is more verbose but leaves no ambiguity: *$queryParams* and *$bodyParams*. — Benjamin
  108589
February 14, 2020 22:12 pmjones@pmjones.io ("Paul M. Jones")
Hi all,

> On Feb 14, 2020, at 10:47, Benjamin Morel morel@gmail.com> wrote: > >> >> What about $query and $body? That would be closer to the terminology >> used in HTTP RFCs. > > > The problem is that $body is typically used to get the raw message body as > a string or stream. > > I was thinking more something along the lines of $bodyParams, which is more > verbose but leaves no ambiguity: *$queryParams* and *$bodyParams*.
I get the desire to disambiguate. But as an added consideration, there's a desire for consistency; when adding a -Params suffix to those names, it might then make sense to have $serverParams, $cookieParams, etc. Looking at it that way, I don't think a -Params suffix is necessary. I would think $query would be enough. As for the other name, the one for the $_POST equivalent, $body doesn't seem quite right to me; it seems a little close to $content. I've also been thinking about $values, $params, $parsedContent, $contentValues, $bodyValues, $contentArray, and other variations with and without prefixes and suffixes, but $input is the one that feels like the least-terrible alternative to $post for me, esp. given the connection to php://input. -- Paul M. Jones pmjones@pmjones.io http://paul-m-jones.com Modernizing Legacy Applications in PHP https://leanpub.com/mlaphp Solving the N+1 Problem in PHP https://leanpub.com/sn1php
  108591
February 15, 2020 08:01 larry@garfieldtech.com ("Larry Garfield")
On Fri, Feb 14, 2020, at 10:47 AM, Benjamin Morel wrote:
> > > > What about $query and $body? That would be closer to the terminology > > used in HTTP RFCs. > > > > The problem is that $body is typically used to get the raw message body as > a string or stream. > I was thinking more something along the lines of $bodyParams, which is more > verbose but leaves no ambiguity: *$queryParams* and *$bodyParams*. > > — Benjamin
Data point: In PSR-7, the names used are: - queryParams: The query string values. - parsedBody: The body of the message, converted to a meaningful value. If the request type is a form, then it MUST be equivalent to $_POST. If not, it's up to the particular implementation to determine what "parsed" means. (Eg, parsing a JSON body of a POST into some domain object, or whatever.) - The raw body is a stream called "body", or rather an OOP wrapper around a stream since PHP's native stream interface is fugly. - There's specific handling for uploadedFiles, too. cf: https://www.php-fig.org/psr/psr-7/ To the earlier point about existing implementations, while there are a myriad of older, custom implementations of abstractions around superglobals, there's only two that are not decade-old proprietary implementations: HttpFoundation and PSR-7. Those are, realistically, the only implementations that matter. Anything else would be on the same order of magnitude effort to port to one of those as to port to this proposal. In a meaningful sense, those are the only "existing competition". Both also have robust ecosystems that make leveraging them in an entirely custom app pretty straightforward. (Whatever your feelings of the technical merits of either design, that's the current state-of-the-market.) Which therefore begs the question, is this proposal intended to supplant HttpFoundation and PSR-7, or to become a common underpinning that both of them wrap, or to be a third cohabitating implementation in the ecosystem? It doesn't seem robust enough to supplant both of them entirely, there's little value to either HttpFoundation or PSR-7 to rewrite their guts to wrap this object (though it's easier for PSR-7, as an interface, for someone to write a new implementation of it than for HttpFoundation), which would mean we'd end up with a 3rd in-the-wild implementation for user space to keep track of. I am unclear how that is a market win. PDO was mentioned previously as a model. Yes, there were many user-space implementations prior to PDO. PDO effectively supplanted and obsoleted them. However... PDO was also never thought-through enough or robust enough to be used directly, spawning a whole new ecosystem of PDO++ libraries that people actually use (Doctrine, Eloquent, Drupal's DBTNG, Aura..sql, to name but a few). So, not the full win people were hoping for. If that pattern holds, we'd end up with... a new generation of this-RFC++ wrappers that still abstract it away yet aren't compatible with each other. That said, PDO did have the advantage of at least partially unifying disparate SQL APIs. There really aren't multiple incompatible HTTPs to abstract over the way there is for SQL backends, so the analogy is somewhat weak either way. --Larry Garfield
  108607
February 15, 2020 20:10 pmjones@pmjones.io ("Paul M. Jones")
Hi all,

> On Feb 15, 2020, at 02:01, Larry Garfield <larry@garfieldtech.com> wrote: > > ... is this proposal intended to supplant HttpFoundation and PSR-7 ... ?
This is question is answered in the RFC introduction; quoting from there: The SQLite “about” page says, “Think of SQLite not as a replacement for Oracle but as a replacement for fopen().” https://www.sqlite.org/about.html Likewise, think of this RFC not as a replacement for HttpFoundation or PSR-7, or as a model of HTTP messages, but as an object-oriented alternative to superglobals, header(), setcookie(), setrawcookie(), and so on.
> PDO was mentioned previously as a model.
I did not mention PDO as "a model". I mentioned PDO (along with other extensions) to illustrate a counter-argument to objections based on the availability and comparability of userland implementations. The counter-argument summary was: That's not to say "because PDO was allowed into core, this RFC must therefore be allowed into core" but to say "those objections alone were not a barrier to PDO, so they alone should not be a barrier to this RFC". The argument, and my counter-argument, are here: <https://externals.io/message/108436#108493> -- Paul M. Jones pmjones@pmjones.io http://paul-m-jones.com Modernizing Legacy Applications in PHP https://leanpub.com/mlaphp Solving the N+1 Problem in PHP https://leanpub.com/sn1php
  108613
February 16, 2020 01:37 rowan.collins@gmail.com (Rowan Tommins)
On 15 February 2020 20:10:30 GMT+00:00, "Paul M. Jones" <pmjones@pmjones.io> wrote:
>Hi all, > >> On Feb 15, 2020, at 02:01, Larry Garfield <larry@garfieldtech.com> >wrote: >> >> ... is this proposal intended to supplant HttpFoundation and PSR-7 >... ? > >This is question is answered in the RFC introduction
You've cut Larry's question in half there, and in doing so made it seem like a repeat, when it is not. The second half of the sentence is this:
> ...or to become a common underpinning that both of them wrap, or to be a third cohabitating implementation in the ecosystem?
I haven't seen you answer that part yet: do you expect existing userland libraries to migrate from wrapping $_GET etc to using these built-in wrappers. If so, what benefit does it bring those libraries? If not, who is its intended audience? You said previously:
> PDO did not (to my knowledge) "add capabilities which cannot exist in userland or cannot exist in a reasonably performant way".
I think this is a misjudgement, and a relevant one. PDO didn't take functionality that existed purely in userland and migrate it to an extension; it took functionality that was scattered across a dozen different vendor-specific extensions with different naming and calling conventions, and centralised it into one more-or-less consistent interface. In doing so, it made (or at least tried to make) life easier both for database vendors, who can provide a PDO driver and fit into the ecosystem, and library developers, who can use PDO as a base and have less vendor-specific code. Your other examples - date, phar, and session - took common problems that were possible to solve in userland but tricky to solve well, and provided a standard out-of-the-box implementation. We already have a unified out-of-the-box implementation for the problem "get data out of HTTP request", in the form of superglobals, so neither comparison seems apt. A better comparison might be to features which have been reimplemented multiple times, to fix fundamental problems. A recent example is __serialize, but interestingly $_GET et al are themselves the third implementation of the feature, after "register globals" and the $HTTP_* arrays. As far as I can see, the RFC mentions two things it fixes about the current implementation: - The current implementation is not OO. That's not really surprising, since PHP is not a purely OO language, and treats OO as a matter of style - to the extent of providing hybrid object-procedural APIs like date and mysqli. - The current implementation is based on global state. This is definitely something that would be good to fix, but you can do almost as much in that direction as the RFC by writing "$get=$_GET; unset($_GET);" The hard problem is that the entry point for a request is in global scope, not a main() or handleRequest() function. Introducing these objects as part of a new calling convention for PHP scripts would definitely add value, and make them a true replacement for the superglobals, but that would be a very different RFC. However well designed this extension is within itself, I think it needs a stronger description of who should use it and why. Regards, -- Rowan Tommins [IMSoP]
  108650
February 17, 2020 15:55 pmjones@pmjones.io ("Paul M. Jones")
Hi Rowan,

I apologize in advance for the length of this email. I hate reading walls-of-text, but the answers are necessarily long. I have tried to break it up into bullets where possible for easier reading.


> On Feb 15, 2020, at 19:37, Rowan Tommins collins@gmail.com> wrote: > > On 15 February 2020 20:10:30 GMT+00:00, "Paul M. Jones" <pmjones@pmjones.io> wrote: > >> Hi all, >> >>> On Feb 15, 2020, at 02:01, Larry Garfield <larry@garfieldtech.com> >>> wrote: >>> >>> ... is this proposal intended to supplant HttpFoundation and PSR-7 >>> ... ? >> >> This is question is answered in the RFC introduction > > You've cut Larry's question in half there, and in doing so made it seem like a repeat, when it is not. The second half of the sentence is this: > >> ...or to become a common underpinning that both of them wrap, or to be a third cohabitating implementation in the ecosystem? > > I haven't seen you answer that part yet: do you expect existing userland libraries to migrate from wrapping $_GET etc to using these built-in wrappers. If so, what benefit does it bring those libraries? If not, who is its intended audience?
I really did think the answers to these were obvious, or easily-inferred, but obviously I was wrong. I will attempt to expand. Q: "Do you expect existing userland libraries to migrate ... ?" A: To be clear, I don't *expect* anything from existing published library authors; however ... - I *suspect* that some will choose to ignore this extension, - that others will decorate or extend it, - and that still others may find their own work so close to this extension that they migrate over to it entirely. Further ... - I suspect that developers of in-house unpublished request/response objects may find this useful for their own purposes, - and that developers who are using $_GET, header(), etc. will be pleased to find an OO-ish system that operates much like PHP itself already does, easing their transition away from global state. Finally ... - I suspect that some *consumers* of existing libraries will feel this extension is not their preferred way of working, and continue on with whatever libraries they already use, - while other consumers of those libraries will prefer this extension in their place. On reading over this, I suppose I do have an "expectation" of library authors and their consumers: that as good engineers they will evaluate this extension in reference to their own circumstances, and choose to use it (or not use it) based on the tradeoffs they find for their situation. Q: "What benefit does it bring those libraries?" A: Whatever benefits their authors happen to see in it. For myself, and as noted by Jan Schneider and others, those benefits center around having a built-in OO-ish request/response object set that does pretty much just what PHP itself already does, and that is well-suited to our daily work, without needing to incorporate comparatively large libraries into our projects for what we consider to be relatively simple purposes -- those purposes being "reading the request inputs" and "sending the response outputs". Q: "Who is its intended audience?" A: I always thought of the "intended audience" as the much the same as for any RFC: that is, developers working on a website who want PHP to provide a reasonable set of functionality for doing so, request/response objects being part of that set in a language as closely related to the web as PHP is. (As a fun side note: for all its apparent simplicity, this is an extraordinary question. Unless I have missed something, I don't recall it being asked directly of any RFC before. A Google search against wiki.php.net and externals.io reveals a double-handful of results on the terms "intended audience" and "target audience", but the only even indirect question about it on an RFC is in relation to the JIT, here: <https://externals.io/message/103903#103995> -- and it's by you. :-) * * * Rowan, you quoted Larry asking if this extension was ...
>> to be a third cohabitating implementation in the ecosystem?
.... that is, third after HttpFoundation and PSR-7. (By way of preamble, and to reiterate what I've said before: I would prefer to discuss this RFC on its own terms. But, as you and others want some discussion in context of other projects, I will do so. My apologies if I sound negative or critical toward those projects.) It turns out the question is kind of a funny way of describing the situation, in that PSR-7 is not an implementation of anything. (Full disclosure: I was a sponsor on the PSR-7 proposal.) PSR-7 is instead a set of interfaces; that is, they "are abstractions around HTTP messages and the elements composing them." <https://www.php-fig.org/psr/psr-7/> The meta document notes, "the goal of this proposal is not to obsolete the current interfaces utilized by existing PHP libraries. This proposal is aimed at interoperability between PHP packages for the purpose of describing HTTP messages." <https://www.php-fig.org/psr/psr-7/meta/> So, to refer to PSR-7 as a "cohabiting implementation" is a bit mistaken (but a very easy mistake to make -- I imagine I have made it myself occasionally). If we are going to talk about implementations in an ecosystem, then, there are at least four for PSR-7: - Cake - Guzzle - Slim - Zend/Laminas There are others as well, with varying ranges of adoption; and, as PSR-7 is an interoperability specification, I predict there will be more implementations later. The above implementations are partially but not always fully interchangeable; while they adhere to the PSR-7 method interfaces, they each have their own behavioral idiosyncrasies. In some cases they offer additional methods and behaviors that the others do not have. (This is not a criticism, merely an observation.) Thus, if one wishes to speak in terms of "cohabiting implementations", ext/request would have to be counted as one of at least six (i.e., itself, HttpFoundation, and the above four). I don't know if that strengthens or weakens the ext/request case, but it does help to clarify the world in which it exists. * * * Rowan, you wrote:
> You said previously: > >> PDO did not (to my knowledge) "add capabilities which cannot exist in userland or cannot exist in a reasonably performant way". > > I think this is a misjudgement, and a relevant one. PDO didn't take functionality that existed purely in userland and migrate it to an extension; it took functionality that was scattered across a dozen different vendor-specific extensions with different naming and calling conventions, and centralised it into one more-or-less consistent interface. In doing so, it made (or at least tried to make) life easier both for database vendors, who can provide a PDO driver and fit into the ecosystem, and library developers, who can use PDO as a base and have less vendor-specific code.
That is one valid way of looking at it; but then, on exactly the same terms, it is likewise valid to say that AdoDB "took functionality that was scattered across a dozen different vendor-specific extensions with different naming and calling conventions, and centralised it into one more-or-less consistent interface." So did PEAR DB, Metabase, MDB, and so on. PDO did it as an extension, instead of in userland, but the goals and outcomes noted were identical. I find this more confirmatory than not regarding my earlier counter-argument; i.e., that (in hindsight) objections based on the existence and availability of userland projects would not themselves have been a barrier to PDO, and so should not themselves be a barrier to this RFC.
> Your other examples - date, phar, and session - took common problems that were possible to solve in userland but tricky to solve well, and provided a standard out-of-the-box implementation. > > We already have a unified out-of-the-box implementation for the problem "get data out of HTTP request", in the form of superglobals, so neither comparison seems apt.
Perhaps; working by analogy is always a difficult and imperfect task.
> A better comparison might be to features which have been reimplemented multiple times, to fix fundamental problems. A recent example is __serialize, but interestingly $_GET et al are themselves the third implementation of the feature, after "register globals" and the $HTTP_* arrays. > > As far as I can see, the RFC mentions two things it fixes about the current implementation: > > - The current implementation is not OO. That's not really surprising, since PHP is not a purely OO language, and treats OO as a matter of style - to the extent of providing hybrid object-procedural APIs like date and mysqli.
"As a matter of style" is a good line! In support of that line, this RFC does not seek to remove $_GET and the response-related functions, but rather to provide an additional OO-ish approach that honors the existing (as you say, the third-time's-the-charm) language-level approaches. FWIW, I had considered mentioning the dual OO+procedural APIs of mysqli, date, etc. but it seemed too much in an already-long RFC; I'm glad you brought it up, as I did have it in mind.
> - The current implementation is based on global state. This is definitely something that would be good to fix, but you can do almost as much in that direction as the RFC by writing "$get=$_GET; unset($_GET);" The hard problem is that the entry point for a request is in global scope, not a main() or handleRequest() function.
Another "hard" problem is carrying those values around in the system once they are decoupled from global state; the objects in this RFC purport to do so.
> Introducing these objects as part of a new calling convention for PHP scripts would definitely add value, and make them a true replacement for the superglobals, but that would be a very different RFC.
That does seem rather ambitious. If you feel that's a valuable thing to add to PHP, perhaps it could be part of a future RFC, maybe even one that uses the objects in this RFC as a starting point. * * * Again, my apologies for the wall-of-text. Please let me know if you find those answers are sufficient or not. -- Paul M. Jones pmjones@pmjones.io http://paul-m-jones.com Modernizing Legacy Applications in PHP https://leanpub.com/mlaphp Solving the N+1 Problem in PHP https://leanpub.com/sn1php
  108618
February 16, 2020 11:49 mike@newclarity.net (Mike Schinkel)
> On Feb 15, 2020, at 3:01 AM, Larry Garfield <larry@garfieldtech.com> wrote: > > Data point: > > In PSR-7, the names used are: > > - queryParams: The query string values. > - parsedBody: The body of the message, converted to a meaningful value. If the request type is a form, then it MUST be equivalent to $_POST. If not, it's up to the particular implementation to determine what "parsed" means. (Eg, parsing a JSON body of a POST into some domain object, or whatever.) > - The raw body is a stream called "body", or rather an OOP wrapper around a stream since PHP's native stream interface is fugly. > - There's specific handling for uploadedFiles, too. > > cf: https://www.php-fig.org/psr/psr-7/ > > To the earlier point about existing implementations, while there are a myriad of older, custom implementations of abstractions around superglobals, there's only two that are not decade-old proprietary implementations: HttpFoundation and PSR-7. Those are, realistically, the only implementations that matter. Anything else would be on the same order of magnitude effort to port to one of those as to port to this proposal. In a meaningful sense, those are the only "existing competition". Both also have robust ecosystems that make leveraging them in an entirely custom app pretty straightforward. > > (Whatever your feelings of the technical merits of either design, that's the current state-of-the-market.) > > Which therefore begs the question, is this proposal intended to supplant HttpFoundation and PSR-7, or to become a common underpinning that both of them wrap, or to be a third cohabitating implementation in the ecosystem? > > It doesn't seem robust enough to supplant both of them entirely, there's little value to either HttpFoundation or PSR-7 to rewrite their guts to wrap this object (though it's easier for PSR-7, as an interface, for someone to write a new implementation of it than for HttpFoundation), which would mean we'd end up with a 3rd in-the-wild implementation for user space to keep track of. > > I am unclear how that is a market win.
The win is it allows developer to provide a simple to use object oriented interface *in core*. IOW, without having to bring in an external PHP-code implementation that may or may not break in the future. Another big win would be to allow developers to deprecate use of superglobals in their own apps. However Paul do not want to add an ini setting to disable the use of superglobals. But how could disabling superglobals be done in HttpFoundation or PSR-7? Maybe Paul will reconsider adding such an capability to his RFC because it is something we cannot get with HttpFoundation and PSR-7. Or maybe we should be looking at is a core implementation of PSR-7 instead; one that would allow us to disable access to the superglobals? One that people could subclass, of course. If we did that, we might hash out why some developers do not use PSR-7 and possibly fix its (perceived?) faults in a new PSR to amend PSR-7. -Mike