简体   繁体   English

如何在PHP中的现有类中添加方法?

[英]How to add a method to an existing class in PHP?

I'm using WordPress as a CMS, and I want to extend one of its classes without having to inherit from another class; 我正在使用WordPress作为CMS,我想扩展其中一个类,而不必继承另一个类; ie I simply want to "add" more methods to that class: 即我只想在该类中“添加”更多方法:

class A {

    function do_a() {
       echo 'a';
    }
}

then: 然后:

function insert_this_function_into_class_A() {
    echo 'b';
}

(some way of inserting the latter into A class) (将后者插入A类的某种方式)

and: 和:

A::insert_this_function_into_class_A();  # b

Is this even possible in tenacious PHP? 这在顽固的PHP中甚至可能吗?

If you only need to access the Public API of the class, you can use a Decorator : 如果您只需要访问该类的Public API,则可以使用Decorator

class SomeClassDecorator
{
    protected $_instance;

    public function myMethod() {
        return strtoupper( $this->_instance->someMethod() );
    }

    public function __construct(SomeClass $instance) {
        $this->_instance = $instance;
    }

    public function __call($method, $args) {
        return call_user_func_array(array($this->_instance, $method), $args);
    }

    public function __get($key) {
        return $this->_instance->$key;
    }

    public function __set($key, $val) {
        return $this->_instance->$key = $val;
    }

    // can implement additional (magic) methods here ...
}

Then wrap the instance of SomeClass: 然后包装SomeClass的实例:

$decorator = new SomeClassDecorator(new SomeClass);

$decorator->foo = 'bar';       // sets $foo in SomeClass instance
echo $decorator->foo;          // returns 'bar'
echo $decorator->someMethod(); // forwards call to SomeClass instance
echo $decorator->myMethod();   // calls my custom methods in Decorator

If you need to have access to the protected API, you have to use inheritance. 如果您需要访问protected API,则必须使用继承。 If you need to access the private API, you have to modify the class files. 如果需要访问private API,则必须修改类文件。 While the inheritance approach is fine, modifiying the class files might get you into trouble when updating (you will lose any patches made). 虽然继承方法很好,但修改类文件可能会让您在更新时遇到麻烦(您将丢失所有补丁)。 But both is more feasible than using runkit. 但两者都比使用runkit更可行。

An updated way for 2014 that copes with scope. 2014年的更新方式,可以应对范围。

public function __call($method, $arguments) {
    return call_user_func_array(Closure::bind($this->$method, $this, get_called_class()), $arguments);
}

Eg: 例如:

class stdObject {
    public function __call($method, $arguments) {
        return call_user_func_array(Closure::bind($this->$method, $this, get_called_class()), $arguments);
    }
}

$obj = new stdObject();
$obj->test = function() {
    echo "<pre>" . print_r($this, true) . "</pre>";
};
$obj->test();

You can use the runkit extension for this, but you should really consider regular inheritance instead. 您可以使用runkit扩展 ,但您应该考虑使用常规继承。

See runkit_method_add . 请参阅runkit_method_add

If the class in question implements __call magic, then it's possible, and quite easy. 如果有问题的类实现__call魔术,那么它是可能的,而且非常简单。 If you want to know how this works I suggest you read Extending objects with new methods at runtime . 如果你想知道它是如何工作的,我建议你在运行时阅读用新方法扩展对象

No you can't dynamically change a class during runtime in PHP. 不,你不能在运行时在PHP中动态更改类。

You can accomplish this by either extending the class using regular inheritance: 您可以通过使用常规继承扩展类来实现此目的:

class Fancy extends NotSoFancy
{
    public function whatMakesItFancy() //can also be private/protected of course
    {
        //    
    }
}

Or you could edit the Wordpress source files. 或者您可以编辑Wordpress源文件。

I'd prefer the inheritance way. 我更喜欢继承方式。 It's a lot easier to handle in the long run. 从长远来看,处理起来要容易得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM