Reputation: 12403
I am working with anonymous functions where I am creating anonymous function outside of the object, and then adding it to an object later in which it will be used with __callStatic magic function. The closures that are being added to contain methods from the parent class. I am wondering if I would be able to call those methods from the closure?
Right now I get this error:
EmptyObject::addMethod('open', function(){
if (static::_hasAdapter(get_class(), __FUNCTION__))
return self::_callAdapter(get_class(), __FUNCTION__, $details);
echo '<p>You have mail!</p>';
});
throws this error:
Fatal error: Cannot access static:: when no class scope is active in
And
//Add the functions
EmptyObject::addMethod('open', function(){
if (EmptyObject::_hasAdapter('EmptyObject', __FUNCTION__))
return EmptyObject::_callAdapter('EmptyObject', __FUNCTION__, $details);
echo '<p>You have mail!</p>';
});
throw this error because the method is protected
Fatal error: Uncaught exception 'BadMethodCallException' with message 'Method '_hasAdapter' was not found in class EmptyObject'
Upvotes: 11
Views: 8834
Reputation: 189
Simply store the class name and pass it to the closure via use
. You can call any public static method or grab public static properties or constants this way. If the closure is passed off to a different context it will still work as long as the correct value for $class
was passed to it when it was created. Works for php 5.3:
class test {
public static function callMe() { echo 'call me '; }
public static function runTest() {
$class = __CLASS__;
$call = function() use ($class) {
$class::callMe();
};
$call();
}
}
test::runTest();
Upvotes: 14
Reputation: 151
You can achieve this by using Closure::bind() (PHP >= 5.4.0)
abstract class EmptyObject
{
protected static $methods = array();
final public static function __callStatic($name, $arguments)
{
return call_user_func(self::$methods[$name], $arguments);
}
final public static function addMethod($name, $fn)
{
self::$methods[$name] = Closure::bind($fn, NULL, __CLASS__);
}
final protected static function protectedMethod()
{
echo __METHOD__ . " was called" . PHP_EOL;
}
}
Now any anonymous function passed to EmptyObject::addMethod() will be run in the scope of the EmptyObject class
EmptyObject::addMethod("test", function()
{
self::protectedMethod();
});
// will output:
// EmptyObject::protectedMethod was called
EmptyObject::test();
Upvotes: 15