Hi all,

Replying to both Marco Pivetta and Joe Watkins here, as some of their critiques 
overlap. I apologize in advance for the length of this email.

* * *

On Jan 6, 2017, at 10:47, Marco Pivetta <ocram...@gmail.com> wrote:

> Bundling the [PSR-7] interface is no biggie, so I suggest steering away and 
> going that way

It's a bigger deal than one might think. But again, I have no desire to 
highlight the negatives of PSR-7 in this discussion.

I'd much rather discuss the RFC on its own merits, which Marco does next:

> There are several technical issues too:
>
>  * A magic constructor that fetches data from global state: add a factory for 
> that, leave the constructor open for modifications or new instantiation ways, 
> or make it private.

I get that. John and I tried both variations, and found that the static-factory 
version was clunkier than we expected. For example, if ServerRequest uses a 
static factory, then users extending the ServerRequest class will additionally 
have to write their own factory. Having the constructor just "felt" better when 
we used it. But, I am willing to revisit that decision if needed.

As far as global state: yeah, I hear you. Since ServerRequest is intended to 
encapsulate the superglobals, it seemed reasonable to have it default to 
copying the superglobals internally. Note that the `__contruct(array $globals = 
[])` signature allows for a complete override of whatever you want. (The 
vagaries of JIT population come into play here as well.)


>  * Magic read-only properties that go against the language semantics: make 
> 'em accessors, or do whatever you want, but don't invent new language 
> semantics just for your own extension.

You're right that it's not often seen. However, public read-only properties are 
not a new invention for this RFC. They already exist, such as in 
PDOStatement::$queryString <https://secure.php.net/pdostatement>.

FWIW, the use of a public read-only property turns out to be very practical in 
daily work. Instead of variations on ...

    $request->getPost(); // returns the whole array
    $request->getPost($key); // returns a value in the array
    $request->getPost($key)[$subkey]; // returns a sub-value in the array
    $request->getPost($key, $default); // returns a value, or a default if not 
present

... you work with the property like any other array:

    $request->post;
    $request->post[$key];
    $request->post[$key][$sub];
    $request->post[$key] ?? $default;

It's just that the property is read-only, and you get an exception if you try 
to change it (same as with PDOStatement::$queryString, if I recall correctly.)



>  * A series of non-exhaustive properties that give some "helper" API to see 
> if it's XHR or not, violating basic SRP. Are you abstracting a request or 
> what you want to do with the request? You can define separate utility 
> functions for that. Yes, functions.

/me nods

They are definitely non-exhaustive; the list of properties was put together 
from several reference projects that have classes similar to ServerRequest 
(more on that below).

When some of those projects had a use for for a particular value, I figured it 
made sense to include it here. (If you or others want to provide patches to 
make it more exhaustive, so much the better!)

As for being a violation of the single-responsibility principle, I don't know. 
It seems reasonable to think that if the object contains (e.g.) 
`$request->server['HTTP_FORWARDED']`, it might do well to contain a parsed 
version of the same information as an array in `$request->forwarded`.


>  * As per current API, I'd expect the ctor to throw an exception when used 
> outside the web SAPI context

I will defer to John Boehr on this one. I do wonder how difficult that would 
make it to test at the command-line, or include in command-line testing 
environments (e.g. PHPUnit).


>  * You use the *with* prefix for setting values, while you know exactly that 
> *with* was used to differentiate from a mutable and a non-mutable API in the 
> existing request abstractions: this makes things confusing again

I'm sorry, I don't understand the criticism here. The `ServerRequest::with*()` 
methods do in fact provide an immutable API (a pretty strict one at that). That 
is, they return a new copy of the ServerRequest object with the changed values, 
leaving the original copy unchanged. Maybe I'm not getting what you're saying 
... ?


>  * There's no interface for these classes, and they are not marked as final, 
> as far as I can see. This means that users will extend them (unwise choice), 
> and with that they will have a class with reflection bits in the extension 
> (extremely bad idea!). An interface and final are needed here.

Extensibility is an intended option. Many classes in PHP can be extended, to 
good effect (e.g., PDO).  But I am willing to be hear about why this is a bad 
call -- can you expand on your reasoning?

> I am obviously defensive and biased here

Sure; anyone would be. Thanks for being up-front about it though. :-)

* * *

On Jan 7, 2017, at 06:00, Joe Watkins <pthre...@pthreads.org> wrote:
>
> Regardless of the details of the implementation, I feel it necessary to point 
> out that this is a surprising RFC.

My apologies for giving you cause to be surprised. I thought I had broadcast my 
intentions back in September <http://news.php.net/php.internals/96156> but 
obviously I failed. My bad.


> There are extensions that are absolutely a core part of the ecosystem that 
> remain outside of php-src because that is where they belong. xdebug is one, 
> apc was another, redis, memcached, and a whole list of others besides.

Noted. Honestly I figure at best this extension has only 1 chance in 3 of 
getting accepted.

However, as I think it is central to the operation of PHP in its primary use 
cases (i.e., reading superglobals and sending back response 
headers/cookies/content), taking that chance seems worthwhile.


>   * it is not restricted by what is possible outside of php-src (as phpdbg 
> was)

FWIW, I have not found it possible to provide read-only public properties in 
userland, especially when extending a parent class that wants to enforce the 
read-only nature of those properties. This is central to the intent of 
ServerRequest.

Further, as far as I know, it is not possible to detect if a variable is a 
reference in userland. Doing so is a prerequsite to enforcing immutability, 
which ServerRequest intends to do.

I am of course happy to be corrected on this, as it would solve other problems 
I have had elsewhere.

* * *

Both Joe and Marco had a similar observation.

Marco said:

> if something new is being designed for inclusion in php-src, and it has to 
> reach millions of developers, it better be *reeeeeealli* good. ... IMO needs 
> another few design iterations, and a lot more adoption, in order to become 
> interesting. Orrrrr you provide us with a factory for an implementation of 
> these concepts that already has adoption, traction and extremely careful 
> design behind it.

Joe said:

>
>   * it doesn't have any user base
> 
> ...
>
> I think if you really want to push this forward, the best place to do that is 
> outside the core, where you can pick a release schedule not bound by php-src, 
> where the API can shift because of the will of consumers, rather than 
> internals (dis)ability to agree on anything so contrived as how we should 
> handle HTTP transactions.
>
> The day may come where an abstraction is so popular that we should consider 
> merging it into core, dedicating our time to maintaining it, and even 
> possibly allow it to deprecate and completely replace the current API ...

You are both completely correct, of course, that this extension has so little 
adoption as to be virtually unknown. It is, in itself, a infant.

However, its design is born from commonalities across many different projects, 
from many different authors. They all independently settled on broadly similar 
solutions to the problem of dealing with PHP superglobals, and PHP global 
functions for sending response elements, in a more OO-ish way.

Links to references, and longer explanation of the "broadly similar solutions" 
are in my blog post at <http://paul-m-jones.com/archives/6494>. Meanwhile, note 
that the reference projects include Aura, Cake, Code Igniter, Horde, Joomla, 
Lithium, MediaWiki, Phalcon, Symfony (and thereby Drupal and Laravel), Yaf, 
Yii, and Zend Framework. That's a mere dozen that are themselves representative 
of wide swaths of other parts of PHP userland.

So it is true that this extension, per se, is not widely adopted. But it is 
also true the collection of ideas and solutions it represents is widely vetted 
and broadly agreed-upon in intent, if not in the names of specific classes, 
methods, and properties.


-- 
Paul M. Jones
pmjone...@gmail.com
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

Reply via email to