I ran the following code on 5.0.4 and 5.1.0 with identical results...
Could someone shed light one whether the observed behaviour is
intentional and/or correct?
I expected that one of the following would occur (which obviously doesn't :-):
-
the line commented with 'SET 2' would trigger a
call to __set() (which should fail?). -
the key "test" would be set in the array returned
by __get() but not it the relevant array stored in
$this->array["insideArray"].
The reason I question whether what si observed below is wanted behaviour is
because I thought the __set() functionality was there to be able
to protect/control what stuffed into an object ... but apparently it's
rather easy to side step.
tia,
Jochem
<?php
class T {
private $array = array();
public function __get( $key ) {
echo "Getting $key\n";
return $this->array[$key];
}
public function __set( $key, $value ) {
echo "Setting $key\n";
$this->array[$key] = $value;
}
}
$t = new T;
$t->insideArray = array(); // SET 1
$t->insideArray["test"] = "testing!"; // SET 2
var_dump( $t );
?>
OUTPUT:
Setting insideArray
Getting insideArray
object(T)#1 (1) {
["array:private"]=>
array(1) {
["insideArray"]=>
array(1) {
["test"]=>
string(8) "testing!"
}
}
The __set() method is called when a property of a class is set, __get()
when a property is retrieved.
An array is simple a way of listing things; the array itself is a piece
of data. When you set a key in that array, you are not setting the
array. It may help to think of it like this:
$t = new T;
$t->insideClass = new T;
$t->insideClass->test = "testing!";
In this case, should __set() be called for both lines? Or only for the
first? An array is exactly the same, except you cannot define a __set()
method on it.
Anyway, I don't think this question belongs in internals, imho.
-[Unknown]
-------- Original Message --------
I ran the following code on 5.0.4 and 5.1.0 with identical results...
Could someone shed light one whether the observed behaviour is
intentional and/or correct?I expected that one of the following would occur (which obviously
doesn't :-):
the line commented with 'SET 2' would trigger a
call to __set() (which should fail?).the key "test" would be set in the array returned
by __get() but not it the relevant array stored in
$this->array["insideArray"].The reason I question whether what si observed below is wanted behaviour is
because I thought the __set() functionality was there to be able
to protect/control what stuffed into an object ... but apparently it's
rather easy to side step.tia,
Jochem
Unknown W. Brackets wrote:
The __set() method is called when a property of a class is set, __get()
when a property is retrieved.An array is simple a way of listing things; the array itself is a piece
of data. When you set a key in that array, you are not setting the
I know these things.
array. It may help to think of it like this:
it's doesn't because object != array. as long as you stick to nesting objects
in this way everything is fine because __set() is called on the object
returned by __get() at the previous level - meaning control is maintained
by the object.
basically if I have an overloaded property that is an array I can bork it's
contents completely from outside of the object and the object doesn't get
anything to say about it.
medical analogy to observed behaviour:
if your liver was an array, then I could operate on your liver without you
ever knowing - heck I could remove it completely - regardless of any medical
training. can I assume you would rather keep control of who does what to your
liver?
$t = new T;
$t->insideClass = new T;
$t->insideClass->test = "testing!";
In this case, should __set() be called for both lines? Or only for the
first?
I'd expect that, __set() be called on $t in the first line and
on the second line __get() to be called on $t and __set() on
object $t->insideClass. assuming that class T is defined as in my previous
post.
An array is exactly the same, except you cannot define a __set()
method on it.Anyway, I don't think this question belongs in internals, imho.
I'm not asking how it works. or how to use it but whether it's intended.
(something which STFW or RTFM doesn't enlighten me about) which is why I ask
the people that wrote the functionality (I figure they would know what the
intention is/was).
let me guess, you think it belongs on php-generals? well I'm asking this
question based on a discussion held there - and nobody offered any kind of
answer ... in fact I justed checked and one of the other guys on the thread in
question (subject: "Overloading Limitation- Can Someone Confirm?") now has
a variation of the code we were playing with that segfaults in 5.0.4 and causes
a 'FATAL: emalloc()' error in 5.1.1 (I don't have a newer version at hand
but the other guy reports very odd behaviour in (I assume in 5.1.2) the code in
question is:
<?php
class T {
private $array = array();
public function __get( $key ) {
echo "Getting $key\n";
return $this->array[$key];
}
public function __set( $key, $value ) {
echo "Setting $key\n";
$this->array[$key] = $value;
}
}
$t = new T;
$t->insideArray = array('a' => 'A', 'b' => 'B', 'c' => 'C');
foreach ($t->insideArray as $k => $v) {
$t->insideArray[$k] = null;
}
if (count($t->insideArray) > 0) {
foreach ($t->insideArray as $k => $v) {
echo $v;
}
}
var_dump($t);
?>
5.0.4 OUTPUT:
Setting insideArray
Getting insideArray
Getting insideArray
Getting insideArray
Getting insideArray
Getting insideArray
Segmentation fault
5.1.1 OUTPUT:
Setting insideArray
Getting insideArray
Getting insideArray
Getting insideArray
Getting insideArray
Getting insideArray
Getting insideArray
FATAL: emalloc(): Unable to allocate 1916888421 bytes
I have sneaking suspicion that that's not meant to happen.
rgds,
Jochem
Write your __set to not allow arrays to be set, and make arrays within
your object private or objects with __set in their own right.
You could in fact create a "CustomArray" or something and allow
CustomArrays to be __set'd in your object, then control their contents
with CustomArray->__set().
There's no problem here.
Matthew C. Kavanagh wrote:
Write your __set to not allow arrays to be set, and make arrays within
your object private or objects with __set in their own right.You could in fact create a "CustomArray" or something and allow
CustomArrays to be __set'd in your object, then control their contents
with CustomArray->__set().There's no problem here.
I don't even want to set arrays as overloaded properties and if I did
I could come up with another hundred workarounds to avoid the problem -
the ability to workaround a problem doesn't mean there is not a problem.
I posed the question after trying to help someone with a question posed
on php-generals ... and finding that the behaviour was actually rather strange
and unintuitive (imho);
Its still trivial to make php segfault when using __get()/__set() - I really
don't care what I do with php, a segfault should never occur, at worst I get
a nice FATAL ERROR telling what an idiot I have been... my tests with APC 3.0.10
show that despite the best efforts of mr. Lerdorf et al it is still segfaults
intermittently when using [lots of?] objects (of varying complexity) that use
__get()/__set()/__call()/etc - the last 24 hours lead me to suspect that not APC
but the engine itself is the 'bad guy' ... unfortunately I don't have the C skills
to test that theory.
I suggest that you quit your bitching and start filing some solid bug
reports instead.
http://bugs.php.net
--Wez.
Its still trivial to make php segfault when using __get()/__set() - I really
don't care what I do with php, a segfault should never occur, at worst I get
a nice FATAL ERROR telling what an idiot I have been... my tests with APC 3.0.10
show that despite the best efforts of mr. Lerdorf et al it is still segfaults
intermittently when using [lots of?] objects (of varying complexity) that use
__get()/__set()/__call()/etc - the last 24 hours lead me to suspect that not APC
but the engine itself is the 'bad guy' ... unfortunately I don't have the C skills
to test that theory.
Jochem Maas wrote:
[snip]
my tests with
APC 3.0.10
show that despite the best efforts of mr. Lerdorf et al it is still
segfaults
intermittently when using [lots of?] objects (of varying complexity)
that use
__get()/__set()/__call()/etc - the last 24 hours lead me to suspect that
not APC
but the engine itself is the 'bad guy' ... unfortunately I don't have
the C skills
to test that theory.
Uh, no C skills required:
- Disable APC
- Test
- If problem still occurs, APC is not the culprit
For crying out loud, if PHP is segfaulting then (assuming you didn't
compile it with -fomg-really-fast-optimisation-thing) file a bug report!
--
Jasper Bryant-Greene
General Manager
Album Limited
http://www.album.co.nz/ 0800 4 ALBUM
jasper@album.co.nz 021 708 334