First of all, thank you for taking time to awser my last post. > I don't think "more magic" is neccessarily good thing.
Good point, it's sometimes hard to find out what ten simple lines of code do (in any language) due to obscure or missing documentation and strange coding conventions. But is it a reason to prevent *good* coders (i don't argue here i'm one) from using it disabling a feature ? > LB>> The python rule : if we have a __get, __set, __call, we use it. > no LB>> more no less. > > This will: > a) slow down *a lot* any class that has accessors That's why languages like perl and c# provide a way to define per property accessors. Someone already asked for this feature in php and i think it could be usefull. > b) put all the variable handling on the user (you will have to check > *each* access to the class property, with no opt-out). Accessors are for special usage and won't be use in 100% of classes, i'm convinced that developpers are able to choose to sacrifice a small amount of performances or not. > c) make impossible or unclear to work with classes that both have > defined variables and have accessors I understand you view but i disagree with this argument. My point is that users don't have to know that accessors are called (except if they really want of course). What they just have to know is what properties are accessibles and what's their types. So users have a simple interface with a small amount of methods an properties. It's up to developpers to explain their work to other maintainers. > - either we get loops or we get some hard-to-catch magic - you > will never know if the access to variable will call accessor or not. Here again, it up to the developper to do a correct job. Infinite loops and hard-to-catch magic are not reserved to accessors. A coder can generate a large amount of bugs with a simple 'if' but this feature is present in php :) Concerning class maintainers, in the current design they'll know if accessors are called only after carefully reading the code of __get __set and __call and after listing defines variables. They also have to think about the script process, will the property be set or unset? Won't another accessor modify the object's properties dictionnary? At this time, php can't ensure the developper's accessor will be called. In a python like design, they see the 'function __get' and they know it will be called whatever object context is, that's a good point to avoid bugs and to understand 'magic'. (Here i don't say python do that so you must do that, i try to explain why it's good.) > I don't know Python ways, but from your explanation is looks to me > neither simple, nor clean. As for power, Assembler is powerful too :) > That's strictly IMHO, of course. Well, i hope it's not due to my english. But from your message i understood that we don't have the same conception of accessor usage and now i understand the current design. - php accessors : used to catch calls to undefined variables and undefined functions on an object. - c#/perl/python accessors : used to intercept variables get/set and methods calls. May be __get __set __call names (same names as python) made me think php would implement a feature i'm fond of in other languages. I'll ask you to take this message as a 'feature request' and i'll try to explay why i think the current design does not allow 'cleanly' this feature. > LB>> 2 - create a private hashtable which will handle undeclared > variables LB>> (because once a variable is set in the object's > properties array, __get LB>> and __set won't work anymore with it) > > Right. That's why you use accessors, not - you don't want variables to > be manipulated directly. Yes but why hidding them from class users sight whereas they will (virtually) use them in their programs through $object->varname ? I mean the object interface should declare the "var $varname;" as this var will exists in the class. > LB>> 3 - create the __get() method so we can retrieve the variable > from the LB>> private hashtable. > > That you will have to do in any case. In my last message the variable 'bar' was public, a call to $foo->bar would return null or false so the user know the variable value is not already set. No need to create a __get() > LB>> 4 - disable error_reporting(E_ALL) because $object->myvar is not > LB>> declared and you can't ask it in your code. > > That has nothing to do with it - accessor should take care for this, > it won't both call accessor and issue warning. Yes, but and it's symptomatic of the current design problem (still IMHO), and it will create more problems in php classes using the feature as a way to intercept regular get/set/call. The class developper will have to implement it's own name system to check that the wanted property or method is allowed (the current error reporting do it well already). This makes me confident in the idea that the current design mustn't be used to intercept 'wanted' get/set/call but only as another name error reporting system. ("error: you're trying to call a function that do not exists", "error: the variable you requested does not exists"). PHP already have an object property system, why building another one on top of it making the developper work longer and harder to maintain ? In other languages the aim is just to give the developper a way to 'overload' get set and call using the current class properties and methods without having to build a new independant context for the object. > I don't see how this would make the code ugly. 1. variables doesn't appear in class definition wheareas the user can use them. 2. the absolute need to create a private hashtable to handle variables the user will use whereas he can't see them. 3. the absolute need to create a getter for a setter 4. the need to recode this system everytime you wan't to use accessors. > And I don't see how you could allow to recursively call accessors in your > model Simple : function __get($var) { // this is a recursive call to __get() $temp = $this->someTestValue; // this is not a recursive call, direct access to object // property named $var return object_get($this, $var); } This feature had been thinked by more than one language developpers, it's not my own extravagant idea. > (BTW, current model could allow recursion in some cases - your should > have recursion always prohibited, unless you prevent /by internal PHP means/ > accessors from touching variables inside the object at all). Again, i think developpers know what they do while creating a __get, __set or __call. If the documentation says : IMPORTANT : if __get() is defined, every call to $object->anyvarname will be intercepted by the __get() method. To avoid infinite recursion in __get() use 'object_get()' function. There no way to mistake. And again 'if', 'for' and 'while' generate bug when incorrectly used. The only argument i retain from your response is the performance one. It's true that __get will be called everytime a script try to access a property of an object that contains a __get accessor. What you propose is a way to select variables which will invoque the __get / __set. That's a good idea but moving them from the object to a private hashtable destructurate the class conception. If you want to gain performances, then allowing a per property getter/setter would be enough and would make the code easier to understand. for example something like : class Foo { var $bar; getter $bar {...} setter $bar($value) {...} }; This is a feature request :) > LB>> - when will "use()" be implemented (a package attempt i bet) ? > > What is "use()"? Nothing to to with __get __set __call, and i can't exactly know what it is as it's not documented nor implemented, but try the following code : <?php use('foo'); ?> > LB>> - get_class_methods() do not return methods array when used on a > LB>> namespaced class > > Submit a bug report with code example. You may also want to copy the > report (with code example, if I didn't mention this yet) to the list. > This is not only for this, but also for any other things you think are > bugs. Code example does great things to syncronize about what is the > problem. i'll submit a report, this code show the problem <?php class Buz { function baz(){} }; print_r( get_class_methods('Buz') ); // echo // Array // ( // [0] => baz // ) class Foo::Bar { function baz(){} }; print_r( get_class_methods('Foo::Bar') ); // echo nothing ?> Thanks for reading Laurent -- PHP Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php