Recursive references in container->member objects
Posted: Wed May 24, 2006 6:09 am
Hi,
I'm currently re-writing a browser-based game I maintain and develop for a fan community site. The original game was unclassed and I wanted to incorporate some of the benefits of inheritance and extension by rewriting it to use a class hierarchy.
However, I'm having trouble with an aspect of PHP references and would appreciate any pointers or explanations of why I'm seeing the behaviour described below. The closest thread I could find here is Self Referencing References, but it doesn't seem to address my specific query. For reference, this is running under PHP 4.3 - because the game is a section of a larger site which I do not control, moving up to PHP 5 is not an option at this time.
For this game, I have a number of 'agent' objects to represent players' characters, which are stored in an array which is a member of a 'battle' object. Thus the battle object 'contains' a number of agent objects, which need to be able to influence the battle object from their own methods. To accomplish this, each agent object stores a reference to the battle object which contains it. (This is the top level of the model; in the actual game, the agent objects similarly contain 'tactic' and 'weapon' objects, with references to the owning agent object.)
The following code is a minimal test case of this setup:
The print_r statement gives the following results:
Notice that the only the contents array of the referenced Container object is picked up as being recursive. Logically, I expect the recursion tag to start at the container_ref variable of the Content object...
After searching through the PHP documentation (including comments) and various resources, I've tried setting the references inside and outside of the objects' constructors, having the constructor return a reference, setting the container_ref as a reference whilst returning a reference from the Content constructor... Nothing I've tried has made print_r recognise that the container_ref variable of each Content object is just a reference to the variable $a that it's currently printing.
Because I'm not setting references to the Container object within the Content constructor, the case as printed above does correctly reference the Container object even without returning a reference from the Content constructor. This can be checked by adding the following lines to the test case:
and verifying that $a->contents[0...1]->container_ref->id is still the same as $a->id. Therefore, the code should be fine for my actual purpose, but I still want to nail this recursive reference thing. The seeming duplication of the Container object under every Content object is trivial in this case, but when the Container object has a great number of variables and contains futher arrays, printing out a representation of the populated instance for debugging become completely unworkable.
It's just the lack of recognition for the recursion at the level of Content->container_ref that's bugging me. Am I misunderstanding the way print_r figures out / displays recursion? Is this just a 'feature' of classes in PHP 4? Or is there something I can do to get the recursion recognised at the 'logical' level?
Any help appreciated! Thanks.
I'm currently re-writing a browser-based game I maintain and develop for a fan community site. The original game was unclassed and I wanted to incorporate some of the benefits of inheritance and extension by rewriting it to use a class hierarchy.
However, I'm having trouble with an aspect of PHP references and would appreciate any pointers or explanations of why I'm seeing the behaviour described below. The closest thread I could find here is Self Referencing References, but it doesn't seem to address my specific query. For reference, this is running under PHP 4.3 - because the game is a section of a larger site which I do not control, moving up to PHP 5 is not an option at this time.
For this game, I have a number of 'agent' objects to represent players' characters, which are stored in an array which is a member of a 'battle' object. Thus the battle object 'contains' a number of agent objects, which need to be able to influence the battle object from their own methods. To accomplish this, each agent object stores a reference to the battle object which contains it. (This is the top level of the model; in the actual game, the agent objects similarly contain 'tactic' and 'weapon' objects, with references to the owning agent object.)
The following code is a minimal test case of this setup:
Code: Select all
<?php
class Container
{
function Container()
{
$this->id = uniqid('');
$this->contents = array();
}
}
class Content
{
function Content()
{
$this->id = uniqid('');
$this->container_ref = NULL;
}
}
// Create an instance of the Container class
$a = new Container();
// Populate the contents array with Content objects and set references to the Container object
for ($i = 0; $i < 2; $i++) {
$a->contents[$i] = new Content();
$a->contents[$i]->container_ref =& $a;
}
print_r($a);
?>Code: Select all
container Object
(
[id] => 4474381f78ef5
[contents] => Array
(
[0] => content Object
(
[id] => 4474381f78f33
[container_ref] => container Object
(
[id] => 4474381f78ef5
[contents] => Array
*RECURSION*
)
)
[1] => content Object
(
[id] => 4474381f78f67
[container_ref] => container Object
(
[id] => 4474381f78ef5
[contents] => Array
*RECURSION*
)
)
)
)After searching through the PHP documentation (including comments) and various resources, I've tried setting the references inside and outside of the objects' constructors, having the constructor return a reference, setting the container_ref as a reference whilst returning a reference from the Content constructor... Nothing I've tried has made print_r recognise that the container_ref variable of each Content object is just a reference to the variable $a that it's currently printing.
Because I'm not setting references to the Container object within the Content constructor, the case as printed above does correctly reference the Container object even without returning a reference from the Content constructor. This can be checked by adding the following lines to the test case:
Code: Select all
<?php
foreach ($a->contents as $id => $obj) {
$a->contents[$id]->container_ref->id = uniqid('');
}
print_r($a);
?>It's just the lack of recognition for the recursion at the level of Content->container_ref that's bugging me. Am I misunderstanding the way print_r figures out / displays recursion? Is this just a 'feature' of classes in PHP 4? Or is there something I can do to get the recursion recognised at the 'logical' level?
Any help appreciated! Thanks.