> On Feb 12, 2020, at 7:47 AM, Paul M. Jones <pmjo...@pmjones.io> wrote: > > That is essentially what it does now; the difference is that you mimic the > $GLOBALS array at construction time, and the instance locks automatically: > > $request = new ServerRequest([ > '_GET' => ['foo' => 'bar'], > '_COOKIE' => ['id' => 123], > '_SERVER' => $_SERVER, > ]); > // $request is now locked > > The class that contains ServerRequest would then build up that array for the > constructor. > > Do you feel that's close enough to what you're asking for?
No. IMO it should not lock until explicitly locked. Why? Take a look at WordPress. It does a lot of "fixup" to $_SERVER` variables — to deal with badly implemented web servers — to ensure all known variables have a value and that the format of the value is consistent. If you always lock on instantiation then WordPress would have to default to continue using $_SERVER. Or subclass it, but that would generate copying overhead and it would be too easy for programmers to just call ServerRequest() again. Another option actually would be to allow changes to $_SERVER prior to instantiating ServerRequest() the first time. Frankly though, none of those options should ideal, include your current proposed solution. Basically making a copy of $_SERVER so ServerRequest() is not authoritative, but alternately your solution does not allow frameworks to fix the inconsistency across servers. Maybe what would be needed is a single ServerRequest::initialize( $closure ) where the ciosure can do the fixup. This would need to be called before new ServerRequest() is called after which ServerRequest would be locked for changes. > First, I'd have to decline adding request() (or $request) at all; my opinion > is that one ought to be reading from $get, $post, $cookies, etc. > specifically, not from a pool of those values. That's definitely fair. I almost did not include request() in my suggestion but did because PHP has $_REQUEST. > Second, if I understand you correctly, I much prefer the property access over > the method getter; it just "looks and feels better": > > $request->get['foo'] > vs > $request->get()['foo']; > > Let me know if that makes sense to you or not. I was actually proposing a third option: $request->get('foo'); Or as I like to do in my own code (to indicate where it comes from): $request->GET('foo'); Why a method is important is to support filters (I guess I assumed that was obvious but realize now it was not.) For example: $request->get('redirect', FILTER_SANITIZE_URL); $request->get('product_id', FILTER_SANITIZE_NUMBER_INT); $request->get('email', FILTER_SANITIZE_EMAIL); You could potentially even have scoped, easier to remember constants that can work with autocomplete: $request->get('redirect', ServerRequest::URL); $request->get('product_id', ServerRequest::INT); $request->get('email', ServerRequest::EMAIL); > incorporate the functionality of filter_input(). Otherwise we have to bypass > the objects to get filtering. > > I don't think you'd have to bypass the objects to get filtering; unless I am > missing something, this ... > > $foo = filter_input(INPUT_GET, 'foo', FILTER_SANITIZE_SPECIAL_CHARS); > > ... would easily become this: > > $foo = filter_var($request->get['foo'], FILTER_SANITIZE_SPECIAL_CHARS); > > There might be behavioral nuances between the two, but the point is that you > can still do filtering. But wouldn't it be 1000% easier to write and easier to read code like this? $foo = $request->get( 'foo', ServerRequest::SPECIAL_CHARS); Since filtering $_GET elements is 100% done when accessing them it makes sense to streamline the operation. But if a developer does not want to filter, they just do this: $foo = $request->get( 'foo' ); >> Would you not also add an option to generate a warning when using them for >> those who want to deprecate their use in their own code (deprecating across >> the board would be too extreme give how much CMS and framework code uses >> them intimately.) > > That seems a bit much at this point. ;-) Really? Seems like this and some guard code is all it would take: ini_set( "disallow_superglobals", true); -Mike