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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3011910/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 08:24:50  来源:igfitidea点击:

How to add a method to an existing class in PHP?

phpclassextendinheritance

提问by Gal

I'm using WordPress as a CMS, and I want to extend one of its classes without having to inherit from another class; i.e. I simply want to "add" more methods to that class:

我使用 WordPress 作为 CMS,我想扩展它的一个类,而不必从另一个类继承;即我只想向该类“添加”更多方法:

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 中甚至是可能的吗?

回答by Gordon

If you only need to access the Public API of the class, you can use a Decorator:

如果你只需要访问类的公共 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 protectedAPI, you have to use inheritance. If you need to access the privateAPI, you have to modify the class files. 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.

如果您需要访问protectedAPI,则必须使用继承。如果需要访问privateAPI,则必须修改类文件。虽然继承方法很好,但修改类文件可能会让您在更新时遇到麻烦(您将丢失任何补丁)。但两者都比使用 runkit 更可行。

回答by Chris

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();

回答by Artefacto

You can use the runkit extensionfor this, but you should really consider regular inheritance instead.

您可以为此使用runkit 扩展,但您应该真正考虑常规继承。

See runkit_method_add.

runkit_method_add

回答by wimvds

If the class in question implements __call magic, then it's possible, and quite easy. If you want to know how this works I suggest you read Extending objects with new methods at runtime.

如果有问题的类实现了 __call 魔法,那么这是可能的,而且很容易。如果您想知道这是如何工作的,我建议您阅读在运行时使用新方法扩展对象

回答by selfawaresoup

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.

我更喜欢继承方式。从长远来看,它更容易处理。