Comment ajouter une méthode à une classe existante en PHP?

J'utilise WordPress comme CMS, et je veux étendre une de ses classes sans avoir à hériter d'une autre classe; i.e. je veux simplement "ajouter" plus de méthodes à cette classe:

class A {

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

puis:

function insert_this_function_into_class_A() {
    echo 'b';
}

(d'une certaine façon de l'insertion de ce dernier dans Une classe)

et:

A::insert_this_function_into_class_A();  # b

est-ce même possible en PHP tenace?

14
demandé sur Artefacto 2010-06-10 09:45:11

5 réponses

si vous n'avez besoin que d'accéder à L'API publique de la classe, vous pouvez utiliser un Décorateur:

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 ...
}

puis envelopper L'instance de 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

Si vous avez besoin d'avoir accès à l' protected API, vous devez utiliser l'héritage. Si vous avez besoin d'accéder à l' private API, vous devez modifier les fichiers de classe. Alors que l'approche de l'héritage est correcte, modifier les fichiers de classe peut vous causer des problèmes lors de la mise à jour (vous perdrez tous les correctifs apportés). Mais les deux sont plus réalisables que l'utilisation de runkit.

18
répondu Gordon 2010-06-10 07:20:47

une nouvelle façon pour 2014 qui s'adapte à scope.

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

par exemple:

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();
4
répondu Chris 2014-08-13 12:23:26

Vous pouvez utiliser l'extension runkit pour cela, mais vous devriez vraiment envisager l'héritage régulier à la place.

Voir runkit_method_add.

3
répondu Artefacto 2017-02-02 03:21:12

si la classe en question implémente _ _ call magic, alors c'est possible, et assez facile. Si vous voulez savoir comment cela fonctionne, je vous conseille de lire extension des objets avec de nouvelles méthodes à l'exécution.

2
répondu wimvds 2010-06-10 06:18:58

Non vous ne pouvez pas changer dynamiquement une classe pendant l'exécution en PHP.

Vous pouvez accomplir ceci en étendant la classe en utilisant l'héritage régulier:

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

ou vous pouvez éditer les fichiers source Wordpress.

je préférerais l'héritage. C'est beaucoup plus facile à gérer à long terme.

-2
répondu selfawaresoup 2010-06-10 06:24:33