采用这个简单的代码:
class MyClass {
public $customFunction = array();
public function run($name){
call_user_func($this->customFunction[$name]);
}
}
//> Usage:
$c = new MyClass();
$c->customFunction['first'] = function (){ /* some code*/ };
$c->run('first');
这个cose的作用就像被驱逐一样。我将该函数添加到$customFunction
,然后我可以将其称为run();
方法。
问题出现在我注入的函数中,我尝试做一些与对象相关的事情,例如,如果我添加这个函数:
$c->customFunction['first'] = function(){ $this->callsomemethod(); }
当我调用run();
方法时,PHP说我不能在静态上下文中使用$this
。
我是否有办法注入这些功能并能够使用对象方法?
(注意:当然我的课只是一个例子,我需要这个范围)
感谢
public function run($name) {
call_user_func($this->customFunction[$name],$this);
}
此时我只需要添加像这样的parm函数:
= function ($this) { /*some code*/};
$this
将模拟对象上下文范围。
答案 0 :(得分:5)
错误源自您在示例中显示为/* some code*/
的代码。
您可以在此处指定匿名函数:
$c->customFunction['first'] = function (){ /* some code*/ };
它仍然只是一个功能。它不会成为班级的真正方法。因此,在其中使用$this
将无效。
解决方法:将自定义函数传递给$obj
参数,让他们使用该参数代替$this
。 (真的,只是一个古怪的解决方法;但可行。)
call_user_func($this->customFunction[$name], $obj=$this);
或者尝试使用classkit_method_add
或runkit
来获得“正确”的解决方案。 - 如果在PHP中可用。
答案 1 :(得分:1)
抱歉,你无法做到这一点。
然而,像往常一样,我确实有一些诡计。 :)
你可以这样做:
class Test {
static protected $funcs_static=array();
protected $funcs_dynamic=array();
public static function register_static($function){
self::$funcs_static[]=$function;
}
public static function register_dynamic($function){
$this->$funcs_dynamic[]=$function;
}
public function __call($name, $arguments) {
return call_user_func_array($name,$arguments);
}
public static function __callStatic($name, $arguments) {
return call_user_func_array($name,$arguments);
}
}
使用示例:
class MyClass extends Test { }
MyClass::register_static(function(){
echo 'bark';
});
$catdog = new MyClass();
$catdog->register_dynamic(function(){
echo 'beow';
});
答案 2 :(得分:1)
使用对象而不是匿名函数,并遵循以下基本代码:
interface Command {
public function execute();
}
interface MyClassAware {
public function setMyClass(MyClass $myClass);
}
class MyClass {
private $customCommands = array();
public function addCustomCommand($name, Command $command) {
$this->customCommands[$name] = $command;
}
public function execute($name) {
$command = $this->customCommands[$name];
if ($command instanceof MyClassAware) {
$command->setMyClass($this);
}
$command->execute();
}
}
最终用法:
class DoSthCommand implements Command, MyClassAware {
private $myClass;
public function setMyClass(MyClass $myClass) {
$this->myClass = $myClass;
}
public function execute() {
// do sth
$this->myClass->doSthElse();
// do sth
}
}
$myCustomCommand = new DoSthCommand();
$myClass->addCustomCommand('doSth', $myCustomCommand);
$myClass->execute('doSth');
答案 3 :(得分:0)
不幸的是,you can't do that。
你能做的最好的事情(至少没有造成脑损伤)是使用__call魔法并将$ this传递到你的lambda范围内,因为$ something_other_than_ $ this:
<?php
class Greeter {
public $greeting = 'Hi';
public $customFns;
public function __construct($sayHiMethod){
$this->customFns['sayHi'] = $sayHiMethod;
}
public function __call($name,$args){
$args['caller']=$this;
return call_user_func_array($this->customFns[$name],$args);
}
}
$myGreeter = new Greeter(function($who,$caller){ echo "{$caller->greeting}, {$who}!\n"; });
$myGreeter->sayHi('Sally');
输出:
嗨,莎莉!