Newsgroups: php.internals,php.internals Path: news.php.net Xref: news.php.net php.internals:17643 php.internals:17644 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 97631 invoked by uid 1010); 9 Aug 2005 01:41:01 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 97616 invoked from network); 9 Aug 2005 01:41:01 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 9 Aug 2005 01:41:01 -0000 X-Host-Fingerprint: 68.112.247.235 68-112-247-235.static.oxfr.ma.charter.com Received: from ([68.112.247.235:2847] helo=localhost.localdomain) by pb1.pair.com (ecelerity 2.0 beta r(6323M)) with SMTP id 2B/1B-04646-DA908F24 for ; Mon, 08 Aug 2005 21:41:01 -0400 To: internals@lists.php.net,Justin Hannus Message-ID: <42F8099E.4090105@128kb.com> Date: Mon, 08 Aug 2005 21:40:46 -0400 User-Agent: Mozilla Thunderbird 1.0 (Windows/20041206) X-Accept-Language: en-us, en MIME-Version: 1.0 CC: internals@lists.php.net, Derick Rethans , Jan Borsodi , Raymond Bosman , Frederik Holljen , Tobias Schlitt References: <42F80940.7080209@128kb.com> In-Reply-To: <42F80940.7080209@128kb.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Posted-By: 68.112.247.235 Subject: Re: Property Overloading RFC From: jhannus@128kb.com (Justin Hannus) ...And, this could allow static member overloading as well! -Justin Justin Hannus wrote: > The way ActionScript 2.0 solves this is with set and get keywords on > function declarations. Any class can contain as many setter/getters as > they need,. Since we dont want to introduce any new keywords how about > something similar with __set and __get? > > > class Foo > { > private $_fooProp; > > function __set fooProp($val) > { > $this->_fooProp = $val; // $_fooProp is read only > } > > function __set barProp($val) > { > // logic to set barProp... > } > > function __get barProp($val) > { > // logic to get barProp... > } > } > ?> > > To allow for BC, if there is no identifier after the __set/__get then > the existing rules apply. > > -Justin > > Derick Rethans wrote: > >> Hello! >> >> we're finding some problems with property overloading (__get() and >> __set()). Here is an RFC describing what we'd like to see changed. >> Please comment on this. >> >> >> Introduction: >> PHP currently supports property overloading with the magic functions >> __get() >> and __set(). Those methods are called when the code "echo $object->a" or >> "$object->a = 42" are executed and the property "a" is not declared in >> the >> class. The magic methods are responsibly for: >> - checking if the property actually "exists" >> - setting the value or returning the value depending on the action >> >> Problems: >> 1. There is no way to document the 'virtual' properties with any of >> the existing >> documentation tools (such as phpdoc and doxygen) >> 2. There is no way how the magic methods know if a specific 'virtual' >> property >> exists or not as those properties are not declared usually - unless >> you >> define an array with property names as a class constant (which is not >> allowed either). >> 3. There is no way for the magic methods to return a meaningfull error >> when a >> property doesn't "exist". Of course it is possible to throw an >> error with >> "trigger_error" or "throw" in case a property doesn't "exist" in a >> specific >> class, but the file and line numbers would not match the actually >> get/set >> action. debug_backtrace() can be used to retrieve the correct file >> and line, >> but as you have to do this for every class where you want to use >> setters and >> getters *and* you have to implement your own error message rendering >> function this is not really a suitable option either. >> >> >> Solutions: >> - For problem 1. we can introduce a keyword (or use an existing one) >> to define >> that it is a virtual property ('abstract' or 'virtual' come to >> mind). When >> declaring it like this it's easy to document, and we can also implement >> visibility for those virtual properties. Marcus already has a patch >> for >> this somewhere, which uses the "abstract" keyword for this purpose: >> >> > class Base >> { >> /** >> * @var int Contains all X >> */ >> abstract public $x = 1; >> >> /** >> * @var int Contains all Y >> */ >> abstract protected $y = 2; >> >> // abstract private $z = 3; abstract properties cannot be private >> } >> ?> >> >> - In combination to the introduced keyword we need an easy way to >> check if a >> passed property name is declared in the class as 'virtual'. >> Currently (with >> the 'abstract' keyword properly implemented) you'd have to do: >> >> > class Base >> { >> abstract public $x = 1; >> >> function __get($name) >> { >> try { >> $prop = new ReflectionProperty('Base', $name); >> if ( !$prop->isAbstract() ) { >> /* throw error */ >> } >> } catch ($e) { >> /* throw error */ >> } >> } >> } >> >> $b = new Base(); >> echo $b->foo; >> ?> >> >> This is ofcourse overly complicated. A better workable solution >> would be - >> without breaking BC (suggestions for syntax here are very welcome): >> >> > class Base >> { >> abstract public $x = 1; >> >> function __get($name) >> { >> if (!self::isVirtual($name))) { >> /* throw error */ >> } >> } >> } >> >> $b = new Base(); >> echo $b->foo; >> ?> >> >> - Problem 3 can be solved by: >> * allowing optional by-ref parameters to the __set >> and __get function, so that their signatures become: >> >> function __set($name, $value [, &$error] ) >> function __get($name [, &$error] ) >> >> If the parameter is not given things behave just like they do now >> -> __set >> and __get can not throw meaningful errors with the correct >> file/line of the >> conflicting statement >> >> If the parameter is used in the function's declaration and is set to >> "false" when the __set or __get function returns, the engine can >> throw an >> error on the assignment line with the correct file/line >> combination. If >> it's set to "true" (or "null") then the engine should not throw >> any error. >> >> * Use a different __set and __get function for 'abstract' >> properties, then >> the engine can already determine if you're doing something wrong >> before >> executing the __set and __get methods. >> >> >> regards, >> Derick >>