Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:97566 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 91582 invoked from network); 7 Jan 2017 21:12:18 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 7 Jan 2017 21:12:18 -0000 Authentication-Results: pb1.pair.com header.from=pmjones88@gmail.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=pmjones88@gmail.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.218.46 as permitted sender) X-PHP-List-Original-Sender: pmjones88@gmail.com X-Host-Fingerprint: 209.85.218.46 mail-oi0-f46.google.com Received: from [209.85.218.46] ([209.85.218.46:33840] helo=mail-oi0-f46.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id CD/C7-37836-0B951785 for ; Sat, 07 Jan 2017 16:12:16 -0500 Received: by mail-oi0-f46.google.com with SMTP id 3so469737472oih.1 for ; Sat, 07 Jan 2017 13:12:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:content-transfer-encoding:mime-version:subject:date:references :to:in-reply-to:message-id; bh=ggLpVttNE+fVazGZRsYN++komnLptXYF9MJGHwG6/vo=; b=lvKbv3MsE9fPJlZgPx25PavFKbF7lbVoc9S2zz84GtLCGIWjpZRuPtmgVnSfVBEKj0 kNtTPvUg2Vv8hLeG+FgjZV/h6qLJqtbrncL0O81CIg6DzxMOh0CBZ9N66HhVkDgWd27B Omz9RGU7hmyE7noaguYDmZyjo3zxDkPxsxtFLUo9CS9SY8MkdAg4iJisTaieMxzICVGu +H6GTnz7gD2T27MVYT1mOb0ZtOnq7SVT+GCiKhnjKF4ut+uxJqU38W2UULWbAuJW5dmb 3SukNoGliRJ7khbxMPoPxoDxKVtas2huJDKkIiZBp2b3nXrWoWGI9AQcmcxGhGXcFGNg nOHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:content-transfer-encoding:mime-version :subject:date:references:to:in-reply-to:message-id; bh=ggLpVttNE+fVazGZRsYN++komnLptXYF9MJGHwG6/vo=; b=sjNIeKV90WlkihEGvYTCnKH6HB20j1QXUxNR6WoHRqOYezmrnjk/E1OYuBLASb/wSX 6PZp73x1u9B4/ZJ05Wb/xcRJqj4b2qbp5oysqQWWl7rXjUC/yjGFVtkadvEZEKSklXif GU5VhV/04YoxKRQrPtkRgFR8sbY7dMlmon4k21dAgVeG5iR/nwyuLil+rsv7l/V2/TET RfNQ5j42bqD9Z1u0VUjxKvHMQ5LeTS9ilnbvHjYZdU/7RG8YL2C+LDalYaq2nRsUW6W2 K2xR2V4U2jQ4DJbi0TpmTiN5uU48+JHA6jS2nwaM0vH73aN5Q9EmRD7M4kXBVZsY6Oz4 L3oA== X-Gm-Message-State: AIkVDXKngX2I/4I5nZBv2sKCmFCIEsXfKy09OVNok+AkHITsTTq37rrnUI9liETOYSirQQ== X-Received: by 10.157.12.172 with SMTP id b41mr4434993otb.105.1483823532019; Sat, 07 Jan 2017 13:12:12 -0800 (PST) Received: from [192.168.1.69] (108-236-186-227.lightspeed.nsvltn.sbcglobal.net. [108.236.186.227]) by smtp.gmail.com with ESMTPSA id b16sm39014100ote.19.2017.01.07.13.12.11 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 07 Jan 2017 13:12:11 -0800 (PST) Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Mime-Version: 1.0 (Mac OS X Mail 10.2 \(3259\)) Date: Sat, 7 Jan 2017 15:12:09 -0600 References: To: PHP Internals List In-Reply-To: Message-ID: <0D275F6F-85D3-4E9D-AF89-03C91A23D5BD@gmail.com> X-Mailer: Apple Mail (2.3259) Subject: Re: [PHP-DEV] [RFC][Discussion] ServerRequest and ServerResponse objects From: pmjones88@gmail.com (Paul Jones) 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 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 =3D [])` 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 = . 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 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 = 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 >=20 > ... > > 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 = . 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. --=20 Paul M. Jones pmjones88@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