php 在运行时创建类方法

2022-08-30 16:35:50

我想知道是否有一种方法可以在php中运行时将新方法附加到类中。我的意思是,不是在实例级别,而是直接在类上,以便所有新创建的实例都有这个新方法。这样的事情可以用反思来完成吗?

谢谢


答案 1

是的,可以。

以下是在 php 5.4.x 的运行时中创建方法的方法。

匿名函数由从 5.3.x 开始的 Closure 类表示,从 5.4.x 开始,它添加一个 Closure::bind 静态方法将匿名函数绑定到特定的对象或类。

例:

class Foo {
     private $methods = array();

     public function addBar() {
       $barFunc = function () {
         var_dump($this->methods);
       };
       $this->methods['bar'] = \Closure::bind($barFunc, $this, get_class());
     }

     function __call($method, $args) {
          if(is_callable($this->methods[$method]))
          {
            return call_user_func_array($this->methods[$method], $args);
          }
     }
 }

 $foo = new Foo;
 $foo->addBar();
 $foo->bar();

答案 2

做了一些玩弄整个事情。似乎您唯一可以做的事情就是替换现有方法。但即便如此,这也是间接的。ReflectionClass

我实际上不了解任何基于类的语言,其中存在动态类(话说回来,我的知识非常有限)。我只见过它只在基于原型的语言(javascript,ruby,smalltalk)中完成。相反,在 PHP 5.4 中,您可以做的是使用新方法并向现有对象添加新方法。Closure

下面是一个类,它允许您对任何对象执行此类:

class Container
{
    protected $target;
    protected $className;
    protected $methods = [];

    public function __construct( $target )
    {
        $this->target = $target;
    }

    public function attach( $name, $method )
    {
        if ( !$this->className )
        {
            $this->className = get_class( $this->target );
        }
        $binded = Closure::bind( $method, $this->target, $this->className );
        $this->methods[$name] = $binded;
    }

    public function __call( $name, $arguments )
    {
        if ( array_key_exists( $name, $this->methods ) )
        {
            return call_user_func_array( $this->methods[$name] , $arguments );
        }

        if ( method_exists( $this->target, $name ) )
        {
            return call_user_func_array( 
                array( $this->target, $name ),
                $arguments
                );
        }
    }   
}

若要使用它,必须为构造函数提供现有对象。下面是一些用法示例:

class Foo
{
    private $bar = 'payload';
};
$foobar = new Foo;
// you initial object


$instance = new Container( $foobar );
$func = function ( $param )
{
    return 'Get ' . $this->bar . ' and ' . $param;
};
$instance->attach('test', $func);
// setting up the whole thing


echo $instance->test('lorem ipsum');
// 'Get payload and lorem ipsum'

不完全是你想要的,但AFAIK这是你可以得到的。


推荐