Here's what I want to do:
$var = new ObjectICreated("yay");
echo $var; // outputs "yay" via the __toString() magic method
$var = "Boo"; // $var is still a ObjectICreated, but will now output "Boo" from __toString()
Am I crazy? I think SimpleXML does this very thing, but I'm not sure how. Any thoughts?
Reasoning: I want to track changes to a particular object without having to use billions of getters/setters.
Ok, thanks for the comments, for posterity. SimpleXML DOES do this. The following works based on code from http://www.php.net/manual/en/simplexml.examples-basic.php example #9.
$x = simplexml_load_string($xml); // xml from example #9
// Pre-reference value
print_r($x->movie[0]->characters->character[0]->name);
// Assign to reference of a SimpleXMLElement
$x->movie[0]->characters->character[0]->name = 'Miss Coder';
print_r($x->movie[0]->characters->character[0]->name);
The output is as follows:
SimpleXMLElement Object ( [0] => Ms Coder )
SimpleXMLElement Object ( [0] => Miss Coder )
As you can see, it is still a SimpleXMLElement, as it was prior to the assignment of "Miss Coder".
Thank you again everyone for your time.
Thank you to all who responded. I was able to come up with a solution that works for what I need.
Before I get there, as @PeeHaa stated, the __get and __set magic methods are the way to go here. However, to reach the stated goal of the original post, we require an object hierarchy. As far as I can tell, that's how SimpleXML is able to do what I described in my original post and subsequent edits, again alluded to by @PeeHaa in a comment. My original idea is indeed impossible [deep sigh of regret].
Below is a very primitive view of what I'm going to do to accomplish this. I've done some pre-work and it appears to work as expected. Obviously, I am going to fill this out and refine it to fit my specific needs. It is also missing some sub-object creation code and sub-type intelligence in the interest of brevity.
class Foo {
protected $_value;
protected $children = array();
public function __construct($value) {
$this->_value = $value;
}
public function setValue($value) {
$this->_value = $value;
}
public function __toString() {
return $this->_value;
}
public function __set($key, $value) {
if(isset($this->children[$key]) == false) {
$this->children[$key] = new self($value);
} else {
$this->children[$key]->setValue($value);
}
}
public function __get($key) {
return $this->children[$key];
}
}
$foo = new Foo("");
$foo->myVar = "some value"; // assigns "some value" to $foo->myValue->_value
print_r($foo->myVar); // outputs that we have a Foo
echo $foo->myVar; // outputs the contents of $foo->myValue->_value aka "some value"
// This works and produces the string value of both "myVar" and "anotherVar",
// with "anotherVar" being an instance of Foo.
$foo->myVar->anotherVar = "some other value";
Again, thank you all for your contributions and your patience as I worked this out.
As @dbf says
$var = "Boo"
will overwrite $var no matter what
if you want to avoid getters/setters, you can simply expose a public member
$var = new ObjectICreated("yay");
echo $var; // outputs "yay" from $var->value via the __toString() magic method
$var->value = "Boo";
If you want to prevent a lot of setters/getters you could implement magic setters / getters. Although often this is a code smell.
class Foo
{
private $magicData = array();
public function __set($name, $value)
{
$this->magicData[$name] = $value;
}
public function __get($name)
{
return $this->magicData[$name];
}
}
Now you can simply do the following:
$foo = new Foo();
$foo->something = 'bar';
$foo->reallyAnything = 'baz';
echo $foo->something;