Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:64491 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 83187 invoked from network); 3 Jan 2013 03:25:08 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 3 Jan 2013 03:25:08 -0000 Authentication-Results: pb1.pair.com smtp.mail=cpriest@zerocue.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=cpriest@zerocue.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain zerocue.com designates 67.200.53.250 as permitted sender) X-PHP-List-Original-Sender: cpriest@zerocue.com X-Host-Fingerprint: 67.200.53.250 mail.zerocue.com Received: from [67.200.53.250] ([67.200.53.250:51549] helo=mail.zerocue.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 6E/A2-35624-31AF4E05 for ; Wed, 02 Jan 2013 22:25:08 -0500 Received: from [172.17.0.122] (unknown [66.25.151.173]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by mail.zerocue.com (Postfix) with ESMTPSA id D981F1203A3; Thu, 3 Jan 2013 03:25:03 +0000 (UTC) Message-ID: <50E4FA09.7030001@zerocue.com> Date: Wed, 02 Jan 2013 21:24:57 -0600 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/17.0 Thunderbird/17.0 MIME-Version: 1.0 To: Steve Clay CC: PHP Internals References: <50E41BB6.4030901@zerocue.com> <50E4A43E.6030302@zerocue.com> <50E4B232.5000505@mrclay.org> <50E4BDDE.8050509@zerocue.com> <50E4D0BB.7060701@mrclay.org> In-Reply-To: <50E4D0BB.7060701@mrclay.org> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] [PHP-RFC] Property Accessors 1.2 for Final Review before Vote From: cpriest@zerocue.com (Clint Priest) All great questions Steve, doesn't quite work the way you have here. Specifically each get/set/isset/unset have their own guards (just like __get(), __set(), __isset() and __unset()) which means that: Within get: $this->Hours can read the underlying property but not write to it, if it attempts to write, that write would go through the setter. Within set: $this->Hours = 1 can write to the underlying property but a read of the property would go through the getter. Within isset/unset: the same rules apply, a read goes through the getter and a write goes through the setter. I've updated the Shadowing section of the RFC which I hope clears this up, it also includes a slightly modified version of your example at the bottom with comments. More comments below: On 1/2/2013 6:28 PM, Steve Clay wrote: > On 1/2/13 6:08 PM, Clint Priest wrote: >> Sorry, there was a typo in that RFC there, this line: >> isset { return $this->Hours != NULL; } >> Should have been with !==: >> isset { return $this->Hours !== NULL; } >> >> I've already updated the 1.2 doc to reflect the correct way. >> >> Given what I mentioned above, I'm assuming you did not test this with >> the fork, right? >> Just based your comments on how it should logically work (with the >> incorrect != vs !==?) > > I haven't tested the fork. I just borrowed your logic with the typo :) > >> One last thing about that, the isset/unset with $this->Hours calls >> the getter to retrieve >> the $this->Hours value, so it behaves as your example below indicates. > > The RFC says, "only the accessors themselves may directly access the > shadowed property." I read that as: > > Within get, $this->Hours is the raw shadowed property. > Within set, $this->Hours is the raw shadowed property. > Within isset, $this->Hours is the raw shadowed property. > Within unset, $this->Hours is the raw shadowed property. > But you seem to imply: > > Within get, $this->Hours is the raw shadowed property. > Within set, $this->Hours is the raw shadowed property. > Within isset, $this->Hours is accessed via __getHours()/__setHours(). > Within unset, $this->Hours is accessed via __getHours()/__setHours(). > > So really the default implementations behave like this: > > isset { return $this->__getHours() !== NULL; } > unset { $this->__setHours(NULL); } Technically this is an accurate translation of what happens with the RFC example, but this would work as well. > > I think the RFC should be much clearer about what property access > actually means within each accessor method, as I expect users to be > very surprised by this behavior. > > This is also looks like it could lead to surprises: > > Within get, $this->Hours is the raw shadowed property. > Within get, parent::$Hours is accessed via > parent::__getHours()/parent::__setHours(). I'm not sure I understand what you mean here... within get the parent accessor is accessed via parent::$Hours, internally that is translated to what you have above but none of this parent::__getHours() needs to be typed out, parent::$Hours will suffice. > > Also, is there no way to access the shadow property within > isset/unset? If not, is there a good reason to not allow it? Yes, it would bypass the getter and setter which may be dynamic and never set the underlying property. > Also, do/should multiple property accessors interact? Consider: > > class Foo { > public $a { > get { $this->a = 1; return 2; } > } > public $b { > get { return $this->a; } > } > } > > $foo = new Foo; > $foo->a; // 2 (but shadowed property is 1) > $foo->b; // 1 or 2? This would cause a "Warning, unable to set property Foo::$a, no setter defined." Both of your $foo->a and $foo->b lines would return the return value of the Foo::$a getter which is always 2. The reason it would produce that warning is because you do not have a setter for $a defined and therefore it is read only, even to its-self. Only the setter may set the underlying value. > > Steve Clay -- -Clint