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

Reply via email to