Is it possible to dynamically add code to extend a class?

I want to write some kind of "plugin / module" system for my code, and that would make it easier if I could "add" material to the class after it was defined.

For example, something like this:

class foo {
  public function a() {
     return 'b';
  }
}

There is a class. Now I want to add another function / variable / const to it after its definition.

I understand that this is probably not possible, but I need confirmation.

+3
source share
7 answers

No, you cannot add methods to an already defined class at runtime.

But you can create similar functionality using magic methods __call/__callStatic.

Class Extendable  {
    private $handlers = array();
    public function registerHandler($handler) {
        $this->handlers[] = $handler;
    }

    public function __call($method, $arguments) {
        foreach ($this->handlers as $handler) {
            if (method_exists($handler, $method)) {
                return call_user_func_array(
                    array($handler, $method),
                    $arguments
                );
            }
        }
    }
}

Class myclass extends Extendable {
    public function foo() {
        echo 'foo';
    }
}

CLass myclass2 {
    public function bar() {
        echo 'bar';
    }
}

$myclass = new myclass();
$myclass->registerHandler(new myclass2());

$myclass->foo(); // prints 'foo'
echo "\n";

$myclass->bar(); // prints 'bar'
echo "\n";

This solution is rather limited, but maybe it will work for you.

+5

/ , Decorators / Strategies. OO .

API, . , .

class Decorator 
{
    // …

    public function __construct($decoratedInstance)
    {
        $this->_decoratedInstace = $decoratedInstance;    
    }
    public function someMethod()
    {
        // call original method
        $result = $this->_decoratedInstance->someMethod();
        // decorate and return
        return $result * 10;
    }
    // …
}

. PHP?

+3

.:) .

:

class main_class {
    private $_MODS = array(),...;
    public ...;
    public function __construct(...) {
        ...
        global $MODS_ENABLED;
        $this -> $_MODS = $MODS_ENABLED;
    }
    ...
    public function __get( $var ) {
        foreach ( $this->_MODS as $mod ) 
            if ( property_exists( $mod, $var ) )
                return $mod -> $var;
    }
    public function __call( $method, $args ) {
        foreach ( $this->_MODS as $mod )
            if ( method_exists( $mod, $method ) )
                return call_user_method_array( $method, $mod, $args );
    }
}

, :

class modMe {
    private $_MODS = array();
    public function __construct__() {
        global $MODS_ENABLED;
        $this -> $_MODS = $MODS_ENABLED;
    }
    public function __get( $var ) {
        foreach ( $this->_MODS as $mod ) 
            if ( property_exists( $mod, $var ) )
                return $mod -> $var;
    }
    public function __call( $method, $args ) {
        foreach ( $this->_MODS as $mod )
            if ( method_exists( $mod, $method ) )
                return call_user_method_array( $method, $mod, $args );
    }
}
class mainClass extends modMe {
    function __construct(...){
        $this -> __construct__();
    }
}

:

$MODS_ENABLED = array();
$MODS_ENABLED[] = new mod_mail();
$myObj = new main_class(...);
$myObj -> mail("me@me.me","you@you.you","subject","message/body","Extra:Headers;More:Headers");
# Hey look, my mail class was just added into my main_class for later use.

:

( , ) CMS, (http://sitegen.com.au), , , , _, , . /mods -enabled/* . , . , , , , , .
.

+1

class foo {
  public function a() {
     return 'b';
  }
}

class woo extends foo {
  public function newStuff() {
     $var = $this->a();
     echo $var;
  }
}

Extending foo from the woo class, the functionality in foo is applicable, and you can also create new methods in woo. This is the easiest way to add new functionality to the class.

0
source

You can use the magic PHP functionality to provide actions on methods that are not defined at compile time.

0
source

It is really possible. For instance:

<?php
class Test {

  function set($set, $val) {
    $this->$set = $val;
  }

  function get($get) {
    return $this->$get;
  } 
}

$t = new Test();
$t->set('hello', 'world');
echo $t->get('hello');
exit; 
?>
0
source

If you don't have enough magic, you can use dynamic objects. The general idea is here: https://github.com/ptrofimov/jslikeobject

0
source

Source: https://habr.com/ru/post/1784949/


All Articles