Hi,
I came across a strange behavior when using the magic method __get and
some instance variable that should be an array.
Consider the following example:
class A
{
public function __get($name)
{
$this->$name = array();
return $this->$name;
}
public function test()
{
$this->_zork['bar'] = 67;
}
}
$a = new A;
$a->test();
var_dump($a);
So could someone explain me what is the semantic of the above statements?
Thanks
-- Mathieu Suen
Hi,
This is interesting and it appears the following change makes the
snippet work as expected:
public function &__get($name);
Hi,
I came across a strange behavior when using the magic method __get and
some instance variable that should be an array.
Consider the following example:class A
{public function __get($name)
{
$this->$name = array();
return $this->$name;
}public function test()
{
$this->_zork['bar'] = 67;
}
}$a = new A;
$a->test();var_dump($a);
So could someone explain me what is the semantic of the above statements?
Thanks
-- Mathieu Suen
--
Ionut G. Stan
I'm under construction | http://blog.igstan.ro/
Ionut G. Stan wrote:
Hi,
This is interesting and it appears the following change makes the
snippet work as expected:public function &__get($name);
I think is that the $this->anArray['bar'] = 4;
Generate the following bytcode:
0 FETCH_OBJ_W $0 'anArray'
1 ZEND_ASSIGN_DIM $0, 'bar'
Will the folloing :
echo $this->anArray;
$this->anArray['bar'];
0 FETCH_OBJ_R $0 'anArray'
1 ECHO
...
IMHO I think that the complexity of the VM is way to hight.
That is something I am strongly agree with Gilad Bracha on adding new
feature into a language:
Look at the last paragraph:
http://gbracha.blogspot.com/2009/09/systemic-overload.html
Hi,
I came across a strange behavior when using the magic method __get and
some instance variable that should be an array.
Consider the following example:class A
{public function __get($name)
{
$this->$name = array();
return $this->$name;
}public function test()
{
$this->_zork['bar'] = 67;
}
}$a = new A;
$a->test();var_dump($a);
So could someone explain me what is the semantic of the above
statements?Thanks
-- Mathieu Suen
--Mathieu Suen
Hello,
On Wed, Mar 17, 2010 at 3:40 PM, mathieu.suen
mathieu.suen@easyflirt.com wrote:
Ionut G. Stan wrote:
Hi,
This is interesting and it appears the following change makes the snippet
work as expected:public function &__get($name);
I think is that the $this->anArray['bar'] = 4;
Generate the following bytcode:
0 FETCH_OBJ_W $0 'anArray'
1 ZEND_ASSIGN_DIM $0, 'bar'Will the folloing :
echo $this->anArray;
$this->anArray['bar'];0 FETCH_OBJ_R $0 'anArray'
1 ECHO
...IMHO I think that the complexity of the VM is way to hight.
That is something I am strongly agree with Gilad Bracha on adding new
feature into a language:
What exactly would you like it do? You've two options:
- __get, define the property, and then __set?
- __get returns a ref that is modified
The second option is taken by PHP.
In your case you return a value, not a reference.
Look at the last paragraph:
http://gbracha.blogspot.com/2009/09/systemic-overload.htmlHi,
I came across a strange behavior when using the magic method __get and
some instance variable that should be an array.
Consider the following example:class A
{public function __get($name)
{
$this->$name = array();
return $this->$name;
}public function test()
{
$this->_zork['bar'] = 67;
}
}$a = new A;
$a->test();var_dump($a);
So could someone explain me what is the semantic of the above statements?
Thanks
-- Mathieu Suen
--Mathieu Suen
--
--
Etienne Kneuss
http://www.colder.ch
Etienne Kneuss wrote:
Hello,
On Wed, Mar 17, 2010 at 3:40 PM, mathieu.suen
mathieu.suen@easyflirt.com wrote:Ionut G. Stan wrote:
Hi,
This is interesting and it appears the following change makes the snippet
work as expected:public function &__get($name);
I think is that the $this->anArray['bar'] = 4;
Generate the following bytcode:
0 FETCH_OBJ_W $0 'anArray'
1 ZEND_ASSIGN_DIM $0, 'bar'Will the folloing :
echo $this->anArray;
$this->anArray['bar'];0 FETCH_OBJ_R $0 'anArray'
1 ECHO
...IMHO I think that the complexity of the VM is way to hight.
That is something I am strongly agree with Gilad Bracha on adding new
feature into a language:What exactly would you like it do? You've two options:
- __get, define the property, and then __set?
- __get returns a ref that is modified
The second option is taken by PHP.
In your case you return a value, not a reference.
I think there is a lot to say why is not working but just look at those
2 execution:
---------------- 1st
class A
{
public function __get($name)
{
$this->$name = array();
return $this->$name;
}
public function test()
{
$this->_zork;
$this->_zork['bar'] = 67;
}
}
$a = new A;
$a->test();
var_dump($a);
---------------- 2nd
class A
{
public function __get($name)
{
$this->$name = array();
return $this->$name;
}
public function test()
{
$this->_zork['bar'] = 67;
}
}
$a = new A;
$a->test();
var_dump($a);
Adding something that don't have side effect make the side effect
work.... (more or less)
You almost have to know how the VM is implemented in other to know what
is going on.
Nothing is obvious.
Look at the last paragraph:
http://gbracha.blogspot.com/2009/09/systemic-overload.htmlHi,
I came across a strange behavior when using the magic method __get and
some instance variable that should be an array.
Consider the following example:class A
{public function __get($name)
{
$this->$name = array();
return $this->$name;
}public function test()
{
$this->_zork['bar'] = 67;
}
}$a = new A;
$a->test();var_dump($a);
So could someone explain me what is the semantic of the above statements?
Thanks
-- Mathieu Suen
--Mathieu Suen
--
-- Mathieu Suen
I think there is a lot to say why is not working but just look at those
2 execution:---------------- 1st
class A
{public function __get($name)
{
$this->$name = array();
return $this->$name;
}public function test()
{
$this->_zork;
$this->_zork['bar'] = 67;
}
}$a = new A;
$a->test();var_dump($a);
---------------- 2nd
class A
{public function __get($name)
{
$this->$name = array();
return $this->$name;
}public function test()
{
$this->_zork['bar'] = 67;
}
}$a = new A;
$a->test();var_dump($a);
Adding something that don't have side effect make the side effect
work.... (more or less)
You almost have to know how the VM is implemented in other to know what
is going on.
Nothing is obvious.
On the contrary, it's quite obvious what's going on. In both examples
__get() returns an array as PHP would normally do it (i.e. NOT by
reference) which means that if you try to modify that you'll end up
modifying nothing much. However, in your second example, the point at
which you call __get() indirectly comes before the assign to the zork
array - hence, the $this->zork['blah'] = 'blah'; no longer indirectly
calls __get as object::$zork now exists.
In other words, this is down to you confusing passing a variable by
reference and passing it by value: PHP normally passes arrays by
value, so when __get() returns an array, you're working on a copy of
the array you returned. As someone noted earlier, you can easily
change the behaviour of __get to return variables by reference, should
you want to. However, I personally wouldn't want this to be default
behaviour as that would make debugging apps much more annoying -
things should be consistent, even if consistency at times confuse
people.
Regards
Peter
--
<hype>
WWW: http://plphp.dk / http://plind.dk
LinkedIn: http://www.linkedin.com/in/plind
Flickr: http://www.flickr.com/photos/fake51
BeWelcome: Fake51
Couchsurfing: Fake51
</hype
Peter Lind wrote:
On the contrary, it's quite obvious what's going on. In both examples
__get() returns an array as PHP would normally do it (i.e. NOT by
reference) which means that if you try to modify that you'll end up
modifying nothing much. However, in your second example, the point at
which you call __get() indirectly comes before the assign to the zork
array - hence, the $this->zork['blah'] = 'blah'; no longer indirectly
calls __get as object::$zork now exists.In other words, this is down to you confusing passing a variable by
reference and passing it by value: PHP normally passes arrays by
value, so when __get() returns an array, you're working on a copy of
the array you returned. As someone noted earlier, you can easily
change the behaviour of __get to return variables by reference, should
you want to. However, I personally wouldn't want this to be default
behaviour as that would make debugging apps much more annoying -
things should be consistent, even if consistency at times confuse
people.Regards
Peter
The sementic of
$this->zork
Should be the same as
$this->__get('zork')
So in that respect it is not consistent.
But anywhere I don't care if it change or not.
Look at Scheme, Lisp and Smalltalk language.
This is what I call consistent language.
-- Mathieu Suen
On Thu, Mar 18, 2010 at 5:47 PM, mathieu.suen
mathieu.suen@easyflirt.com wrote:
Peter Lind wrote:
On the contrary, it's quite obvious what's going on. In both examples
__get() returns an array as PHP would normally do it (i.e. NOT by
reference) which means that if you try to modify that you'll end up
modifying nothing much. However, in your second example, the point at
which you call __get() indirectly comes before the assign to the zork
array - hence, the $this->zork['blah'] = 'blah'; no longer indirectly
calls __get as object::$zork now exists.In other words, this is down to you confusing passing a variable by
reference and passing it by value: PHP normally passes arrays by
value, so when __get() returns an array, you're working on a copy of
the array you returned. As someone noted earlier, you can easily
change the behaviour of __get to return variables by reference, should
you want to. However, I personally wouldn't want this to be default
behaviour as that would make debugging apps much more annoying -
things should be consistent, even if consistency at times confuse
people.Regards
PeterThe sementic of
$this->zork
Should be the same as
$this->__get('zork')
$this->zork is only the same as $this->__get("zork") if zork is
undefined, this is perfectly normal and expected.
So in that respect it is not consistent.
But anywhere I don't care if it change or not.
Look at Scheme, Lisp and Smalltalk language.
This is what I call consistent language.-- Mathieu Suen
--
--
Etienne Kneuss
http://www.colder.ch
Etienne Kneuss wrote:
On Thu, Mar 18, 2010 at 5:47 PM, mathieu.suen
mathieu.suen@easyflirt.com wrote:Peter Lind wrote:
On the contrary, it's quite obvious what's going on. In both examples
__get() returns an array as PHP would normally do it (i.e. NOT by
reference) which means that if you try to modify that you'll end up
modifying nothing much. However, in your second example, the point at
which you call __get() indirectly comes before the assign to the zork
array - hence, the $this->zork['blah'] = 'blah'; no longer indirectly
calls __get as object::$zork now exists.In other words, this is down to you confusing passing a variable by
reference and passing it by value: PHP normally passes arrays by
value, so when __get() returns an array, you're working on a copy of
the array you returned. As someone noted earlier, you can easily
change the behaviour of __get to return variables by reference, should
you want to. However, I personally wouldn't want this to be default
behaviour as that would make debugging apps much more annoying -
things should be consistent, even if consistency at times confuse
people.Regards
PeterThe sementic of
$this->zork
Should be the same as
$this->__get('zork')
$this->zork is only the same as $this->__get("zork") if zork is
undefined, this is perfectly normal and expected.
I would be very interested if someone already try to implement a meta
circular interpreter.
So in that respect it is not consistent.
But anywhere I don't care if it change or not.
Look at Scheme, Lisp and Smalltalk language.
This is what I call consistent language.-- Mathieu Suen
-- Mathieu Suen
I guess what Mathieu is trying to say is that this:
class Foo
{
public $bar = array();
}
$foo = new Foo;
$foo->bar[3] = 1;
var_dump($foo);
...is inconsistent with this:
class Foo
{
public function __get($property)
{
if (! isset($this->$property)) {
$this->$property = array();
}
return $this->$property;
}
}
$foo = new Foo;
$foo->bar[3] = 1;
var_dump($foo);
...or even this:
class Foo
{
private $bar = array();
public function __get($property)
{
return $this->$property;
}
}
$foo = new Foo;
$foo->bar[3] = 1;
var_dump($foo);
Now, I'm not really sure this is that bad, as there may be use cases
where one would like to return different values every time __get is
called. And, as I wrote in a previous email, there are ways to work
around this inconsistency by using return by reference, so everybody can
be happy. I think.
On Thu, Mar 18, 2010 at 5:47 PM, mathieu.suen
mathieu.suen@easyflirt.com wrote:Peter Lind wrote:
On the contrary, it's quite obvious what's going on. In both examples
__get() returns an array as PHP would normally do it (i.e. NOT by
reference) which means that if you try to modify that you'll end up
modifying nothing much. However, in your second example, the point at
which you call __get() indirectly comes before the assign to the zork
array - hence, the $this->zork['blah'] = 'blah'; no longer indirectly
calls __get as object::$zork now exists.In other words, this is down to you confusing passing a variable by
reference and passing it by value: PHP normally passes arrays by
value, so when __get() returns an array, you're working on a copy of
the array you returned. As someone noted earlier, you can easily
change the behaviour of __get to return variables by reference, should
you want to. However, I personally wouldn't want this to be default
behaviour as that would make debugging apps much more annoying -
things should be consistent, even if consistency at times confuse
people.Regards
PeterThe sementic of
$this->zork
Should be the same as
$this->__get('zork')
$this->zork is only the same as $this->__get("zork") if zork is
undefined, this is perfectly normal and expected.So in that respect it is not consistent.
But anywhere I don't care if it change or not.
Look at Scheme, Lisp and Smalltalk language.
This is what I call consistent language.-- Mathieu Suen
--
--
Ionut G. Stan
I'm under construction | http://blog.igstan.ro/
Right I could work around the issue with the return by reference without
any problem.
I am still thinking that if you try to write a meta-circular interpreter
you gonna work very hard
to make this subtleties worked. And according to "Shriram Krishnamurthi"
in his textbook PLAI:
" a truly powerful language is one that makes it easy to write its
meta-circular interpreter."
-- Mathieu Suen
Ionut G. Stan wrote:
I guess what Mathieu is trying to say is that this:
class Foo { public $bar = array(); } $foo = new Foo; $foo->bar[3] = 1; var_dump($foo);
...is inconsistent with this:
class Foo { public function __get($property) { if (! isset($this->$property)) { $this->$property = array(); } return $this->$property; } } $foo = new Foo; $foo->bar[3] = 1; var_dump($foo);
...or even this:
class Foo { private $bar = array(); public function __get($property) { return $this->$property; } } $foo = new Foo; $foo->bar[3] = 1; var_dump($foo);
Now, I'm not really sure this is that bad, as there may be use cases
where one would like to return different values every time __get is
called. And, as I wrote in a previous email, there are ways to work
around this inconsistency by using return by reference, so everybody
can be happy. I think.On Thu, Mar 18, 2010 at 5:47 PM, mathieu.suen
mathieu.suen@easyflirt.com wrote:Peter Lind wrote:
On the contrary, it's quite obvious what's going on. In both examples
__get() returns an array as PHP would normally do it (i.e. NOT by
reference) which means that if you try to modify that you'll end up
modifying nothing much. However, in your second example, the point at
which you call __get() indirectly comes before the assign to the zork
array - hence, the $this->zork['blah'] = 'blah'; no longer indirectly
calls __get as object::$zork now exists.In other words, this is down to you confusing passing a variable by
reference and passing it by value: PHP normally passes arrays by
value, so when __get() returns an array, you're working on a copy of
the array you returned. As someone noted earlier, you can easily
change the behaviour of __get to return variables by reference, should
you want to. However, I personally wouldn't want this to be default
behaviour as that would make debugging apps much more annoying -
things should be consistent, even if consistency at times confuse
people.Regards
Peter
Have you considered that perhaps you're trying to use the wrong
language for what you're doing? PHP does what it does now consistently
(in this regard) - what you're suggesting breaks that consistency. To
gain what, exactly?
Right I could work around the issue with the return by reference without any
problem.
I am still thinking that if you try to write a meta-circular interpreter you
gonna work very hard
to make this subtleties worked. And according to "Shriram Krishnamurthi" in
his textbook PLAI:" a truly powerful language is one that makes it easy to write its
meta-circular interpreter."-- Mathieu Suen
Ionut G. Stan wrote:
I guess what Mathieu is trying to say is that this:
class Foo
{
public $bar = array();
}$foo = new Foo;
$foo->bar[3] = 1;var_dump($foo);
...is inconsistent with this:
class Foo
{
public function __get($property)
{
if (! isset($this->$property)) {
$this->$property = array();
}return $this->$property;
}
}$foo = new Foo;
$foo->bar[3] = 1;var_dump($foo);
...or even this:
class Foo
{
private $bar = array();public function __get($property)
{
return $this->$property;
}
}$foo = new Foo;
$foo->bar[3] = 1;var_dump($foo);
Now, I'm not really sure this is that bad, as there may be use cases where
one would like to return different values every time __get is called. And,
as I wrote in a previous email, there are ways to work around this
inconsistency by using return by reference, so everybody can be happy. I
think.On Thu, Mar 18, 2010 at 5:47 PM, mathieu.suen
mathieu.suen@easyflirt.com wrote:Peter Lind wrote:
On the contrary, it's quite obvious what's going on. In both examples
__get() returns an array as PHP would normally do it (i.e. NOT by
reference) which means that if you try to modify that you'll end up
modifying nothing much. However, in your second example, the point at
which you call __get() indirectly comes before the assign to the zork
array - hence, the $this->zork['blah'] = 'blah'; no longer indirectly
calls __get as object::$zork now exists.In other words, this is down to you confusing passing a variable by
reference and passing it by value: PHP normally passes arrays by
value, so when __get() returns an array, you're working on a copy of
the array you returned. As someone noted earlier, you can easily
change the behaviour of __get to return variables by reference, should
you want to. However, I personally wouldn't want this to be default
behaviour as that would make debugging apps much more annoying -
things should be consistent, even if consistency at times confuse
people.Regards
Peter--
--
<hype>
WWW: http://plphp.dk / http://plind.dk
LinkedIn: http://www.linkedin.com/in/plind
Flickr: http://www.flickr.com/photos/fake51
BeWelcome: Fake51
Couchsurfing: Fake51
</hype
You are right I am using the wrong language but i can't help.
Is not me who make the decision. So for want of anything better,
why not try to improve the tool.
Peter Lind wrote:
Have you considered that perhaps you're trying to use the wrong
language for what you're doing? PHP does what it does now consistently
(in this regard) - what you're suggesting breaks that consistency. To
gain what, exactly?Right I could work around the issue with the return by reference without any
problem.
I am still thinking that if you try to write a meta-circular interpreter you
gonna work very hard
to make this subtleties worked. And according to "Shriram Krishnamurthi" in
his textbook PLAI:" a truly powerful language is one that makes it easy to write its
meta-circular interpreter."-- Mathieu Suen
--
-- Mathieu Suen
On Mon, Mar 22, 2010 at 5:12 PM, mathieu.suen
mathieu.suen@easyflirt.com wrote:
You are right I am using the wrong language but i can't help.
Is not me who make the decision. So for want of anything better,
why not try to improve the tool.
Improve it how exactly? I can't see how one can improve this part
while keeping it consistent and/or backward compatible.
Peter Lind wrote:
Have you considered that perhaps you're trying to use the wrong
language for what you're doing? PHP does what it does now consistently
(in this regard) - what you're suggesting breaks that consistency. To
gain what, exactly?Right I could work around the issue with the return by reference without
any
problem.
I am still thinking that if you try to write a meta-circular interpreter
you
gonna work very hard
to make this subtleties worked. And according to "Shriram Krishnamurthi"
in
his textbook PLAI:" a truly powerful language is one that makes it easy to write its
meta-circular interpreter."-- Mathieu Suen
--
-- Mathieu Suen
--
--
Etienne Kneuss
http://www.colder.ch
Hi!
I guess what Mathieu is trying to say is that this:
...is inconsistent with this:
This is because you're doing it wrong. If you intend to modify the
property, return it by-ref. Saying the magic "consistency" word doesn't
change that.
Now, I'm not really sure this is that bad, as there may be use cases
where one would like to return different values every time __get is
called. And, as I wrote in a previous email, there are ways to work
around this inconsistency by using return by reference, so everybody can
be happy. I think.
It's not "the way around this inconsistency" - it's how it is supposed
to work.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Hi,
Hi!
I guess what Mathieu is trying to say is that this:
...is inconsistent with this:This is because you're doing it wrong. If you intend to modify the
property, return it by-ref. Saying the magic "consistency" word doesn't
change that.Now, I'm not really sure this is that bad, as there may be use cases
where one would like to return different values every time __get is
called. And, as I wrote in a previous email, there are ways to work
around this inconsistency by using return by reference, so everybody can
be happy. I think.It's not "the way around this inconsistency" - it's how it is supposed
to work.
So, what's the reasoning behind this design decision? Why is it supposed
to work like this and not the other way around?
--
Ionut G. Stan
I'm under construction | http://blog.igstan.ro/
Hi!
So, what's the reasoning behind this design decision? Why is it supposed
to work like this and not the other way around?
Because when you return something by-value you can not have effects of
its modification reflect on the original value. That's how by-value
works. When you have by-ref return you can modify it and have the
original value change. More here: http://php.net/references
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
I guess you're gonna hate this :)
So what you're saying is that it is consistent with regard to the
implementation of methods/functions, i.e. __get behaves as an
ordinary method.
Hi!
So, what's the reasoning behind this design decision? Why is it supposed
to work like this and not the other way around?Because when you return something by-value you can not have effects of its
modification reflect on the original value. That's how by-value works. When
you have by-ref return you can modify it and have the original value change.
More here: http://php.net/referencesStanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
--
Ionut G. Stan
I'm under construction | http://blog.igstan.ro/
Hi!
So what you're saying is that it is consistent with regard to the
implementation of methods/functions, i.e. __get behaves as an
ordinary method.
Yes, it does.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Stanislav Malyshev wrote:
Hi!
So what you're saying is that it is consistent with regard to the
implementation of methods/functions, i.e. __get behaves as an
ordinary method.Yes, it does.
IMHO __get is not consistent at the first place.
on possible example:
class A
{
protected $foo;
public function __get($name)
{
echo 'GET';
}
public function test()
{
return $this->foo;
}
}
$a = new A;
$a->foo;
$a->test();
-- Mathieu Suen
Hi!
IMHO __get is not consistent at the first place.
on possible example:
It is perfectly consistent. You just need to read what it actually does:
http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members
instead of imagining what it could do.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Stanislav Malyshev wrote:
Hi!
IMHO __get is not consistent at the first place.
on possible example:It is perfectly consistent. You just need to read what it actually does:
http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.membersinstead of imagining what it could do.
Hi,
not the same issue, but slightly related, __call() seems to me a bit
inconsistent with __get(). I'm not sure if this is the right thread to
ask this in, if not, I'll be happy to take this somewhere else :)
__get is called when accessing any inaccessible property, either when
not set or when it is private/protected. But __call() only gets called
when the method is not set, not for private methods. In that case you
get a Fatal error. e.g:
<?php
class foo {
protected $foo = 'bar';
function __get($name) {
return 'getting '.$name."\n";
}
private function bar() {
echo 'private bar';
}
function __call($name, $params) {
echo 'calling '.$name."\n";
}
}
$foo = new foo();
echo $foo->foo;
$foo->bar();
?>
Results in:
getting foo
Fatal error: Call to private method foo::bar() from context '' in
/home/auke/public_html/test/get.php on line 23
I wouldn't mind this if this is how it supposed to work, but the
documentation uses the same terminology for __get and __call:
"__get() is utilized for reading data from inaccessible properties."
and
"__call() is triggered when invoking inaccessible methods in an object
context."
In addition the page
http://www.php.net/manual/en/language.oop5.visibility.php
goes into some detail about when methods are visible and when not,
making no distinction between methods and properties in regard to
visibility, and this page is specifically linked from the page about
overloading, as explaining when __call() should be called:
"The overloading methods are invoked when interacting with properties or
methods that have not been declared or are not visible in the current
scope. The rest of this section will use the terms "inaccessible
properties" and "inaccessible methods" to refer to this combination of
declaration and visibility. "
So it seems to me that the above code should not have produced a fatal
error if the documentation is right... or am I misreading something?
regards,
Auke van Slooten
Muze
Auke van Slooten wrote:
Stanislav Malyshev wrote:
Hi!
IMHO __get is not consistent at the first place.
on possible example:It is perfectly consistent. You just need to read what it actually does:
http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.membersinstead of imagining what it could do.
Hi,
not the same issue, but slightly related, __call() seems to me a bit
inconsistent with __get(). I'm not sure if this is the right thread to
ask this in, if not, I'll be happy to take this somewhere else :)__get is called when accessing any inaccessible property, either when
not set or when it is private/protected. But __call() only gets called
when the method is not set, not for private methods. In that case you
get a Fatal error. e.g:<?php
class foo { protected $foo = 'bar'; function __get($name) { return 'getting '.$name."\n"; } private function bar() { echo 'private bar'; } function __call($name, $params) { echo 'calling '.$name."\n"; } } $foo = new foo(); echo $foo->foo; $foo->bar();
?>
Results in:
getting foo
Fatal error: Call to private method foo::bar() from context '' in
/home/auke/public_html/test/get.php on line 23I wouldn't mind this if this is how it supposed to work, but the
documentation uses the same terminology for __get and __call:"__get() is utilized for reading data from inaccessible properties."
and
"__call() is triggered when invoking inaccessible methods in an object
context."In addition the page
http://www.php.net/manual/en/language.oop5.visibility.phpgoes into some detail about when methods are visible and when not,
making no distinction between methods and properties in regard to
visibility, and this page is specifically linked from the page about
overloading, as explaining when __call() should be called:"The overloading methods are invoked when interacting with properties
or methods that have not been declared or are not visible in the
current scope. The rest of this section will use the terms
"inaccessible properties" and "inaccessible methods" to refer to this
combination of declaration and visibility. "So it seems to me that the above code should not have produced a fatal
error if the documentation is right... or am I misreading something?regards,
Auke van Slooten
Muze
IMHO it worth a new thread
-- Mathieu Suen
Stanislav Malyshev wrote:
Hi!
IMHO __get is not consistent at the first place.
on possible example:It is perfectly consistent. You just need to read what it actually does:
http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.membersinstead of imagining what it could do.
It is not because it is written somewhere in the documentation that it
make sense.
This kind of operation is the kind you want to do with a meta-level, not
the base level.
You could even use mirror and design a security layer:
http://gbracha.blogspot.com/2010/03/through-looking-glass-darkly.html
I don' assume __get should work in "a" or "b" way.
So to clarify IMHO it should not exist at all!
-- Mathieu Suen
Hello,
On Thu, Mar 18, 2010 at 8:49 AM, mathieu.suen
mathieu.suen@easyflirt.com wrote:
Etienne Kneuss wrote:
Hello,
On Wed, Mar 17, 2010 at 3:40 PM, mathieu.suen
mathieu.suen@easyflirt.com wrote:Ionut G. Stan wrote:
Hi,
This is interesting and it appears the following change makes the
snippet
work as expected:public function &__get($name);
I think is that the $this->anArray['bar'] = 4;
Generate the following bytcode:
0 FETCH_OBJ_W $0 'anArray'
1 ZEND_ASSIGN_DIM $0, 'bar'Will the folloing :
echo $this->anArray;
$this->anArray['bar'];0 FETCH_OBJ_R $0 'anArray'
1 ECHO
...IMHO I think that the complexity of the VM is way to hight.
That is something I am strongly agree with Gilad Bracha on adding new
feature into a language:What exactly would you like it do? You've two options:
- __get, define the property, and then __set?
- __get returns a ref that is modified
The second option is taken by PHP.
In your case you return a value, not a reference.I think there is a lot to say why is not working but just look at those
2 execution:---------------- 1st
class A
{public function __get($name)
{
$this->$name = array();
return $this->$name;
}public function test()
{
$this->_zork;
$this->_zork['bar'] = 67;
}
}$a = new A;
$a->test();var_dump($a);
---------------- 2nd
class A
{public function __get($name)
{
$this->$name = array();
return $this->$name;
}public function test()
{
$this->_zork['bar'] = 67;
}
}$a = new A;
$a->test();var_dump($a);
Nothing strange or unexpected here, in "1st" you define $this->_zork
in __get the first time you call it, meaning that you'll bypass the
__get for your next $this->_zork['foo'] = 2;
Adding something that don't have side effect make the side effect
work.... (more or less)
You almost have to know how the VM is implemented in other to know what
is going on.
Nothing is obvious.Look at the last paragraph:
http://gbracha.blogspot.com/2009/09/systemic-overload.htmlHi,
I came across a strange behavior when using the magic method __get and
some instance variable that should be an array.
Consider the following example:class A
{public function __get($name)
{
$this->$name = array();
return $this->$name;
}public function test()
{
$this->_zork['bar'] = 67;
}
}$a = new A;
$a->test();var_dump($a);
So could someone explain me what is the semantic of the above
statements?Thanks
-- Mathieu Suen
--Mathieu Suen
--
-- Mathieu Suen
--
Etienne Kneuss
http://www.colder.ch