是否可以在运行时重命名PHP 5.2中的类方法?是否可以使用Reflection做到这一点?
假设:
class Test
{
public function myMethod()
{
echo 'in my method';
}
}
我希望能够将myMethod()
重命名为oldMethod()
,以便稍后我这样做:
$test = new Test();
$test->oldMethod(); // in my method
$test->myMethod(); // run time error: method does not exist
答案 0 :(得分:4)
来自下面的评论问题:
因为我想在类上安装调用事件处理程序,而没有类知道它,所以我知道用户在实际调用该方法之前从类调用方法。
解决方案:使用装饰器。
class EventDecorator
{
protected $_instance;
public function __construct($instance)
{
$this->_instance = $instance;
}
public function __get($prop)
{
printf('Getting %s in %s', $prop, get_class($this->_instance));
return $this->_instance->$prop;
}
public function __set($prop, $val)
{
printf('Setting %s with %s in %s',
$prop, $val, get_class($this->_instance));
return $this->_instance->$prop = $val;
}
public function __call($method, $args)
{
printf('Calling %s with %s in %s',
$method, var_export($args, TRUE), get_class($this->_instance));
return call_user_func_array(array($this->_instance, $method), $args);
}
}
然后你可以将任何一个类包装进去:
class Foo
{
public $prop;
public function doSomething() {}
}
$foo = new EventDecorator(new Foo);
$foo->prop = 'bar'; // Setting prop with bar in Foo
$foo->prop; // Getting prop in Foo
$foo->doSomething('something');
// Calling doSomething with array (0 => 'something',) in Foo
这可以充实以提供前钩和后钩。您还可以使Decorator使用Subject/Observer Pattern并将事件激发到注册到装饰器的任何其他对象。上面的方法比使用runkit的随机方法monkeypatching更易于维护和理解。
附加说明:
答案 1 :(得分:2)
使用Runkit s runkit_method_rename,您可以执行此操作。
答案 2 :(得分:1)
对于所有问你为什么需要这个的人,我有一个非常相似的想法。我的想法是尝试动态重命名整个PHP类。在我的情况下,它将被用于IRC聊天机器人,我将动态加载和实例化插件,这样我就不需要重新启动机器人,正常运行时间会非常长。这将包括重命名与我将尝试加载的类相同名称的预加载类,这样就不会发生冲突并且可以正常运行。
例如:
我在irc.example.com上运行了$bot
我已经安装并运行了插件test.php,现在当它被加载到内存中时,我可以更改文件test.php而不需要对$bot
进行任何更改
所以我更新了test.php
现在我想让它加载到$bot
,但是$bot
已经有一个测试加载,如果我试图再次包含test.php会发生冲突
所以相反,我们运行一个重命名函数将类测试重命名为类test [计数器的sha1]
然后我们加入'test.php'
$bot->test = new test();
我们有了它,一个更新的测试插件安装并加载到$bot
的内存中,没有重启。
这是所有的理论,但是在用“你为什么甚至需要这种”的态度立刻煽动某人的想法之前,要考虑一下。
我的意思是,让我们诚实一点。你是一个超级天才的几率是多少,他知道有关编程的所有知识,并会知道每个人都会或不需要什么?