怎么给 PHP 对象动态添加方法

2016-12-01 17:43:19 +08:00
 niuoh

网上查了一下给 PHP 类动态添加方法需要类中自带__call 魔术方法
如果类 class A{}
就这样 那怎么动态添加方法呢
支持这样:
$a=new A;
$a->test=function(){};
$a->test();

5538 次点击
所在节点    PHP
8 条回复
Jakesoft
2016-12-01 17:47:00 +08:00
call_user_func($m->test);
ParallelMao
2016-12-01 17:59:30 +08:00
想来你应该是需要这个的。

http://php.net/manual/zh/closure.bind.php
RH
2016-12-01 19:08:47 +08:00
greatonce
2016-12-01 19:57:56 +08:00
class Test{
public $_methodContainer = [];

public function __call($method,$value)
{
if(isset($this->_methodContainer[$method])) {
return call_user_func_array($this->_methodContainer[$method], $value);
}
throw new Exception("The specify method cannot be found", 1);
}
}

// define a new method.
function newMethod($s) {return $s.'hello world';}

$test = new Test;
$test->_methodContainer['test'] = 'newMethod';
echo $t->test('你好 ');
feiyuanqiu
2016-12-01 20:27:05 +08:00
class Test
{
private $dynamicMethods = [];

public function __get($name)
{
return isset($this->dynamicMethods[ $name ]) ? $this->dynamicMethods[ $name ] : null;
}

public function __set($name, $value)
{
if ($this->isClosure($value)) {
$this->dynamicMethods[ $name ] = Closure::bind($value, $this, self::class);;
}
}

private function isClosure($value)
{
return is_callable($value) && get_class($value) === \Closure::class;
}

public function __isset($name)
{
return isset($this->dynamicMethods[ $name ]);
}

public function __call($name, $arguments)
{
if (!isset($this->dynamicMethods[ $name ])) {
trigger_error('Call to undefined method ' . self::class . "::{$name}", E_USER_ERROR);
}

return call_user_func($this->dynamicMethods[ $name ], $arguments);
}
}

$a = new Test();
$a->test = function () {
var_dump($this->dynamicMethods);
};
$a->test();
niuoh
2016-12-02 10:06:58 +08:00
找到正解了 我的意思是 class A{} 类里什么都没有也支持动态添加类方法 且支持$a->test();这样调用
方法如下:
class merge_objs{
private $classArr = array();

function __construct() {
$this -> classArr = func_get_args();
}

function __get($s) {
foreach($this-> classArr as $c) {
if (property_exists($c, $s)) {
return $c -> $s;
}
}
}

function __call($fn,$args) {
foreach($this-> classArr as $c) {
if (method_exists($c, $fn)) {
return call_user_func_array(array($c,$fn),$args);
}
}
}
}

class A{}

class B{
public function test(){
echo test;
}
}

$a=new merge_objs(new A,new B);
$a->test();
v2song
2016-12-02 11:50:43 +08:00
可以学习一下 Laravel Macroable 的思想
```php
class Test
{
use Macroable;
}

Test::macro('say', function ($word) {
echo $word;
});

$test = new Test();

$test->say('hello');
```
zhaohehe
2016-12-30 17:12:19 +08:00
$a = new A;
$b = function(){
//...
};

$b->call($a);

php7 的用法,匿名函数的 call()

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/324639

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX