phpclassdynamicruntimeclass-extensions

PHP Class dynamically extending in runtime


Is it possible to dynamically extend a class object in PHP? And what would be the most elegant way of doing this?

Some example code for further explanation:

class BasicClass {

    private $variable;

    public function BasicFunction() {
        // do something
        $this->variable = 10;
    }

}

class ExtendedClass extends BasicClass {

    public function ExtendedFunction() {
        // do something else with basic class variable
        return $this->variable/2;
    }

}

$A = new BasicClass();

If(condition for extension){

    // A should be of class ExtendedClass
    // and the current class variables should be kept
    // ... insert the magic code here ...
    // afterwards we would be able to use the ExtendedFunction with the original variables of the object

    $A->ExtendedFunction();

}

One way of tackling this would be creating a new object of ExtendedClass and copying all the variables from the old object. But can this be done more elegantly?


Solution

  • Yes. It is possible. One way to do it would be using anonymous classes or simply overwriting the class itself(in your case $A) but that implies a little more logic and it's not as clean, so I won't get into it.

    NOTE: Support for anonymous classes was added in PHP 7.

    Using your example above we can compose the following code(I changed the visibility of the property in order to be able to use it in the extended class. I'd suggest you add a getter rather than changing the visibility).

    class BasicClass {
    
      public $variable;
    
      public function BasicFunction() {
        // do something
        $this->variable = 10;
      }
    
    }
    
    class ExtendedClass extends BasicClass {
    
      public function ExtendedFunction() {
        // do something else with basic class variable
        return $this->variable / 2;
      }
    
    }
    
    $A = new BasicClass();
    
    if (TRUE) {
    
      // A should be of class ExtendedClass
      $A = new class extends ExtendedClass {
    
      };
    
      $A->ExtendedFunction();
    }
    

    Do note that this will overwrite $A. You'll still have all the available methods in it since inheritance is not lost by doing this.


    Obviously whichever approach you take won't be the cleanest way you can do this.

    My answer stands, but if you were to edit your question and provide more details on what it is you want to actually achieve by doing this perhaps a different approach is more suitable.


    You can also achieve some magic using eval and possibly Reflection, but they're so magically magic I refuse to write the answer since it promotes such bad practices.