简体   繁体   中英

PHP binding method to another class

Can i bind method of class Foo to class Bar? And why the code below throws a warning "Cannot bind method Foo::say() to object of class Bar"? With function instead of method code works fine.

class Foo {

    public $text = 'Hello World!';

    public function say() {
        echo $this->text;
    }

}

class Bar {

    public $text = 'Bye World!';

    public function __call($name, $arguments) {
        $test = Closure::fromCallable(array(new Foo, 'say'));
        $res = Closure::bind($test, $this);
        return $res();
    }

}

$bar = new Bar();
$bar->say();

This is currently not supported. If you want to bind a closure to a new object, it must not be a fake closure, or the new object must be compatible with the old one ( source ).

So, what is a fake closure : A fake closure is a closure created from Closure::fromCallable .

This means, you have two options to fix your problem:

  1. Bar must be compatible with the type of Foo - so just make Bar extend from Foo , if possible.

  2. Use unbound functions, like annonymous, static or functions outside of classes.

It is not supported by PHP. However in PHP 7.0 it was kinda possible. Consider this example:

class Foo {
    private $baz = 1;
    
    public function baz() {
        var_dump('Foo');
        var_dump($this->baz);
    }
}


class Bar {
    public $baz = 2;
    
    public function baz() {
        var_dump('Bar');
        var_dump($this->baz);
    }
}


$fooClass = new ReflectionClass('Foo');
$method = $fooClass->getMethod('baz');

$foo = new Foo;
$bar = new Bar;

$closure = $method->getClosure($foo);

$closure2 = $closure->bindTo($bar);

$closure2();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM