|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2005-08-10 16:07 UTC] davydm at gmail dot com
Description:
------------
I have a class which maintains heirachical data, as would be (and, indeed, is) represented with xml. The class basically provides a programmable interface to an xml data transport, allowing for data to be transported from php to a tcl middleware server to be parsed and used. So far, so good.
The best way to explain is to demonstrate:
If I were to load an instance of the object with the following xml:
<data>
<name>Foo</name>
<descr>Bar</descr>
<child>
<name>Childname</name>
<descr>Childdescr></descr>
</child>
</data>
I would get an object which has:
$obj->name == "Foo"
$obj->descr == "Bar"
$obj->child[0]->name == "Childname"
$obj->child[0]->descr == "Childdescr"
and so forth. The class allows for nodes with the same name, which are then placed into an an array, hence the array notation on the child node above.
The oddity I have hit upon seems to be a PHP bug, but I'm well open to suggestions. In programming the class, I wanted a consistent interface with the TCL class I have that handles the same functionality, so there are times when I have replicated interface functions even when they are not necessairly required (for the sake of completeness). One such interface mirroring is the get_child function, which takes in the following arguments:
$childname (string)
$idx (integer)
and returns a reference to the child named by the $childname and pointed to by the $idx (if there is one).
The wierdness is that in the original implementation of get_child, where I just checked that the child name was known and the key existed in the array, I did:
return $this->$childname[$idx];
once I had verified with array_key_exists that the element actually existed, I *always* got back null. If I referenced the child from outside of the class (with $obj->childname[$idx]), the child object is quite alright and there, and alive and all of that.
The wierdness steps up a notch when I change the internals of get_child: instead of just returning the object with:
return $this->$childname[$idx];
I do:
foreach ($this->$childname as $cidx => $child) {
if ($cidx == $idx) {
return $child;
}
}
and VOILA!, I get back the child I was looking for. The code is less efficient, of course, because I have to iterate over the child array. But that's not the thing that really bothers me -- I'm more bothered as to *why* this happens, and the only explanation I can see is something lower-level and internal to PHP
Reproduce code:
---------------
Please have a look at http://dascafe.lesbean.net/hdobj.php.gz , starting at line 289, which is the function definition for get_child. You can also see that I've used a foreach in the function toXML(), instead of using the child indeces and the child_count function, as I originally intended. If I can supply more code, please let me know.
Expected result:
----------------
With the commented out code in place, I expect a reference to a member variable of the class which is itself an object of the same class.
Actual result:
--------------
When I use the commented out code, I get a NULL reference instead of the object. Using the foreach to iterate over each element in the $childname array, and returning the child with a matching index works -- although they should have exactly the same result.
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Dec 03 02:00:01 2025 UTC |
I'm afraid that the giant 25 lines below is the smallest I can get a full example of what I'm talking about, since the problem is a little complex. // begin php code class Foo { function Foo() { $this->arrFoo = array("one", "two", "three"); } function getFoo($name, $idx) { if (array_key_exists($idx, $this->$name)) { return $this->$name[$idx]; } else {print("no $name here of that $idx");} } function getBar($name, $idx) { if (array_key_exists($idx, $this->$name)) { foreach ($this->$name as $fidx => $val) { if ($fidx == $idx) return $val; } } else {print("no $name here of that $idx");} } } $myfoo = new Foo(); $badret = $myfoo->getFoo("arrFoo", 0); // bad return example $goodret = $myfoo->getBar("arrFoo", 0); // kludged good return var_dump($ret); print("<br>"); var_dump($myfoo->arrFoo[0]); // direct access works ok print("<br>"); var_dump($goodret); // end php codeDoesn't matter, I got it. Use $this->{$name}[$idx] syntax in this case, as the Engine can't guess what are you referring to: to $this->{$name[0]} or to $this->{$name}[0]. If you set error_reporting to E_ALL, you'll see appropriate notices.