Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:93667 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 32098 invoked from network); 1 Jun 2016 09:50:01 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 1 Jun 2016 09:50:01 -0000 Authentication-Results: pb1.pair.com smtp.mail=petercowburn@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=petercowburn@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.161.179 as permitted sender) X-PHP-List-Original-Sender: petercowburn@gmail.com X-Host-Fingerprint: 209.85.161.179 mail-yw0-f179.google.com Received: from [209.85.161.179] ([209.85.161.179:35138] helo=mail-yw0-f179.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 88/12-11325-8CFAE475 for ; Wed, 01 Jun 2016 05:50:00 -0400 Received: by mail-yw0-f179.google.com with SMTP id o16so13082502ywd.2 for ; Wed, 01 Jun 2016 02:50:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=35/Xgr+Adolt5EwiqbA1c3Lj89YnoGrSpgapl0BN7sg=; b=IU523rKIl2yMoF7Do3OL4pbL+SsXOk59ubnovYhv0aTIyuH6wm/lLjrBNnYqeg9lP3 PUYkUBNIdYlEnR9UxLuVPFsYUQxlBsDg59IfdCkD8jWhlweb1w3+cufdE8E1Sc6kbJLi v14jyOV37nAJx5eSluX7eqs4qji8K0VMizxctCz+5cxQDUTnvgFFGZgLhxSzsggyrVzu /2fM3xU2fCMN5912RSC+mE7OjoQlP267iiMGWNpRWFF853B7yMEwisWTwMqWWad1YIgO GlE5CDTenrQuUN7IAmXxj7Gz9nTCYUdVcQezVcZl2zDryx8S4Mth/cPufQlRv0Qjnd5p JV2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=35/Xgr+Adolt5EwiqbA1c3Lj89YnoGrSpgapl0BN7sg=; b=jxSlkIDvHUY6Ga4aD63dSGlbSFVjwc5wBdOFed0t8AR18EJ5J2oHwj0F1UOg6EYxNg 3Gome4I3JERHGJmLRSLeMnM+eM6Rx1S1clgAgzohD6wl/9dNwgVW/jOxT6hMJOXAzVAf 7ZJuY6TcYcBlnbiea0/jHB7T6e9DRcaNJo1/6kxoYrWNR8VNkQB+bwfIQsYI5d8aKXrF sdA7bGtUiaRKoGteiIycxkngfmnqWarHPnrPQ7bnNaDNjkA2iYGdkVkv+gSGHPiiXFKU mnCOEBiAyE0ikOpP1KU2rlXbIkYbULI7HWvrReqRtGB7Qc7pr5puQd1QkaVkZXHSp/tl B1GQ== X-Gm-Message-State: ALyK8tK/1MODm8BCihTZ00IHVkv4nWGndH1Z7iFCrJ8adMU1mkWTJaxFSVtCrN4JMQIlYoMPT4opPxpdbd+Lqg== X-Received: by 10.37.33.65 with SMTP id h62mr1705239ybh.58.1464774596727; Wed, 01 Jun 2016 02:49:56 -0700 (PDT) MIME-Version: 1.0 Received: by 10.13.254.193 with HTTP; Wed, 1 Jun 2016 02:49:17 -0700 (PDT) In-Reply-To: References: Date: Wed, 1 Jun 2016 10:49:17 +0100 Message-ID: To: Jesse Schalken Cc: PHP internals Content-Type: multipart/alternative; boundary=001a1143e3c68399540534346990 Subject: Re: [PHP-DEV] Set object properties inline From: petercowburn@gmail.com (Peter Cowburn) --001a1143e3c68399540534346990 Content-Type: text/plain; charset=UTF-8 On 1 June 2016 at 03:15, Jesse Schalken wrote: > Hi internals, > > I often have code dealing with plain old PHP objects with properties and no > methods, either as a substitute for keyword arguments, or to represent a > JSON or YAML document for a web service, configuration file or schemaless > database. > > At the moment, instantiating an object and setting public properties > requires a temporary variable for each object in the structure: > $obj1 = new Obj1(); > $obj1->prop1 = ...; > $obj1->prop2 = ...; > > $params = new FooParams(); > $params->prop1 = ..; > $params->prop2 = ...; > $params->prop3 = $obj1; > > $this->fooMethod($arg1, $arg2, $params); > > > For large structures, this gets verbose very quick. There is a good example > of this here > < > https://github.com/jesseschalken/fail-whale/blob/72870b37c4c21d19f17324a966344ec476b432a7/src/FailWhale/Introspection.php#L22 > > > involving > 18 unnecessarily variables. > > I can remove the local variables by defining setters for all the > properties: > > $this->fooMethod( > > $arg1, > $arg2, > (new FooParams()) > > ->setProp1(...) > > ->setProp2(...) > > ->setProp3((new Obj1()) > > ->setProp1(...) > > ->setProp2(...)) > > ); > > > But now for each property I have to spend an extra 3-5 lines of code > defining a setter, which is more code than it saved (unless the class is > used heavily enough). > > I could define __construct() taking every property as a parameter, but then > each property has to be mentioned another three times (four times with a > doc comment), and the type twice: > > class FooParams { > > public int $prop1; > // ... > > > public function __construct( > int $prop1 > // ... > ) { > > $this->prop1 = $prop1; > // ... > > } > > } > > > and where the object is constructed, it isn't immediately visible what the > meaning of each positional parameter is without some IDE assistance (eg > Ctrl+P in PhpStorm), and only specifying some parameters requires filling > preceding ones with defaults. > > I could also define the __call() method to automatically expose setters, > but then IDEs and static analysis can't understand what's going on (it > can't see that those methods exist, what their parameters are and what they > return). @method doc comments on the class help, but that's another line > for every property which I have to manually keep in sync with the real > properties. > > It would be great if there was a simple shorthand syntax for setting > properties on an object in-line, without needing to extract a variable: > > $this->fooMethod( > $arg1, > $arg2, > new FooParams() { > prop1 = ..., > prop2 = ..., > prop3 = new Obj1() { > prop1 = ..., > prop2 = ..., > }, > } > ); > While it's not as concise as your example, anonymous classes can do this already after a fashion. $this->fooMethod( $arg1, $arg2, new class() extends FooParams { // Constructor because prop3's value isn't a constant expression function __construct() { $this->prop1 = '...'; $this->prop2 = '...'; $this->prop3 = new class() extends Obj1 { public $prop1 = '...'; public $prop2 = '...'; }; } } ); > > > This way the structure can be written directly in the code as an expression > and FooParams and Obj1 remain simple containers for properties. > > The grammar might look like (I haven't used bison/yacc before): > > expr_without_variable: > /* ... */ > | expr '{' inline_set_properties '}' > ; > > inline_set_properties: > /* empty */ > | identifier '=' expr > | identifier '=' expr ',' inline_set_properties > ; > > > (Although I think that would conflict with the alternative $var{8} syntax > for array/string offset.) > > Has this been explored before? What problems can you foresee (or have been > foreseen) with such a feature? > > Thanks > --001a1143e3c68399540534346990--