Page 1 of 1

Php Object Context and trait in version 5.4

Posted: Thu Jun 27, 2013 6:49 pm
by sheikh.Heera
This is my first post here, so please paredone me if I've made any mistakes.
I have a trait like this

Code: Select all

trait MethodBuilder
{
    protected $methods = array();
    public function addMethod($methodName, $callback)
    {
        // ...
        $this->methods[$methodName] = $callback->bindTo($this);
    }

    public function __call($methodName, array $args)
    {
        if (isset($this->methods[$methodName])) {
            return call_user_func_array($this->methods[$methodName], $args);
        }
    }
}
Also a class like this
[syntax]
class Test{
use MethodBuilder;
}
[/syntax]

Then I do
[syntax]
$obj = new Test;
$obj->name="Sheikh Heera";
$obj->addMethod('getName', function(){
return $this->name . '<br />';
});
echo $obj->getName(); // Sheikh Heera, works
[/syntax]

Then another object
[syntax]
$newObj = new stdClass; // tried without this
$newObj->name = "The Rock";
$newObj = clone $obj;
echo $newObj->getName(); // Sheikh Heera, but I expected "The Rock"
[/syntax]
Is that possible ? Looks like the trait is not getting cloned to the $newObg , Ant work around for that ?
An example here : http://codepad.viper-7.com/NPAs1i.
Thanks for your effort :)

Re: Php Object Context and trait in version 5.4

Posted: Fri Jun 28, 2013 12:12 am
by requinix
The trait got "cloned" perfectly fine. What didn't happen is the stdClass::name being copied over to the new Test::name. Which is totally correct because with your assignment the stdClass object gets thrown away and you got an instance of a Test instead.

If you want to "work around" this then clone first and assign the name after.

Code: Select all

$newObj = clone $obj;
$newObj->name = "The Rock";
echo $newObj->getName();

Re: Php Object Context and trait in version 5.4

Posted: Sun Jun 30, 2013 12:36 am
by sheikh.Heera
Thanks! I did it already but didn't work. Check this http://codepad.viper-7.com/dDeMZa.

Re: Php Object Context and trait in version 5.4

Posted: Sun Jun 30, 2013 1:36 am
by requinix
Ah, devious.

The getName closure is being bound to $obj. When you cloned $obj you got getName but that doesn't change what it's bound to. You'd have to rebind it: implement __clone so that it re-binds (which itself clones) each method.

Code: Select all

public function __clone()
{
	foreach ($this->methods as $key => $method)
	{
		$this->methods[$key] = $method->bindTo($this);
	}
}