Variable variable class extensions in PHP--is it possible?

前端 未结 8 1920
囚心锁ツ
囚心锁ツ 2020-12-06 14:22

Is something like the following possible in PHP?

$blah = \'foo1\';

class foo2 extends $blah {
    //...
}

class foo1 {
    //...
}

This g

相关标签:
8条回答
  • 2020-12-06 14:52

    Using PHP overloading you can accomplish this to a certain extent.

    class variable_class {
        public $orginalBaseClass;
        public $orginalArgs;
    
        public function __construct() {
            // Get constructor parameters.
            $this->orginalArgs = func_get_args();
            // Get class name from args or 3rd party source.
            $classname = 'stdClass';
    
            // Pass along args to new class.
            $this->orginalBaseClass = new $classname($this->orginalArgs);
        }
    
        public function __call($name, $arguments) {
            // Pass all method calls to the orginalBaseClass.
            return call_user_func_array(array($this->orginalBaseClass, $name), $arguments);
        }
    }
    

    I'm using this pattern inside a Drupal module for prefetching data from the cache.

    0 讨论(0)
  • 2020-12-06 15:00

    If you don't have too many values for $blah, you could extend each one in a different file then require_once "classes/foo_$blah.php"

    Otherwise, you're stuck with the eval() solution... good luck with that... :)

    0 讨论(0)
  • 2020-12-06 15:05

    I assume that this is for ease-of-maintenance, right? Extending a class at run time really is pretty crazy.

    class SuperClassOne { /* code */ }
    class SuperClassTwo { /* code */ }
    
    class IntermediateClass extends SuperClassOne { /* empty! */ }
    
    class DescendantClassFoo extends IntermediateClass{ }
    class DescendantClassBar extends IntermediateClass{ }
    class DescendantClassBaz extends IntermediateClass{ }
    

    Then, when you want to change all your DescendantClass* classes, you just have to change what the IntermediateClass extends:

    class IntermediateClass extends SuperClassTwo { }
    
    0 讨论(0)
  • 2020-12-06 15:07

    You're assuming here php executes top to bottom, but it doesn't quite work like that:

    <?php
    foo();  # works
    
    function foo(){
      print "bar";
    }
    

    <?php
    
    foo();  #dies
    
    if( $i == 1 )
    {
      function foo(){
        print "bar";
      }
    }
    

    <?php
    $i = 1;
    if( $i == 1 )
    {
      function foo(){
        print "bar";
      }
    }
    
    foo(); #works
    

    Now, although you can conditionally create classes:

    <?php
    
    class A { }
    class B { }
    if( false ){ 
      class C extends B { 
        public static function bar(){
          print "baz"; 
        }
      }
    }
    C::bar(); # dies
    

    You cant instantiate one at runtime from a variable:

    <?php
    class A { }
    class B { }
    $x = 'B'; 
    if( false ){ 
      class C extends $x { 
        public static function bar(){
          print "baz"; 
        }
      }
    }
    C::bar();
    ---> Parse error: syntax error, unexpected T_VARIABLE, expecting T_STRING in /tmp/eg.php on line 7
    

    There is a way to do it with Eval, but you really don't want to go there:

    <?php
    
    class A { }
    class B { }
    $x = 'B'; 
    if( true ){ 
     $code =<<<EOF
      class C extends $x { 
        public static function bar(){
          print "baz"; 
        }
      }
    EOF;
    
      eval( $code );
    }
    C::bar();
    $o = new C; 
    if ( $o instanceof $x )
    {
      print "WIN!\n";
    }
    --->barWIN!
    

    However, there is a more important question here:

    Why the hell would you want to extend a different class at runtime

    Anybody using your code will want to hold you down and whip you for that.

    ( Alternatively, if you're into whipping, do that eval trick )

    0 讨论(0)
  • 2020-12-06 15:07

    I don't see how this would be particularly useful, but to answer your question... no. There's no way to dynamically do that because the generated class has to be instantiated before the variable is evaluated (if that makes sense).

    To put it simply: The class must exist before the code can be properly executed.

    0 讨论(0)
  • 2020-12-06 15:07

    I tested something with defines and barking:

    <?php
        define("INHERIT",A);
    
        class A{
            public function bark(){
                return "I'm A";
            }
        }
        class B{
            public function bark(){
                return "I'm B";
            }
        }
    
        class C extends INHERIT{}
    
        //main?
        $dog = new C();
        echo $dog->bark();
    ?>
    

    the output is:

    Fatal error: Class 'INHERIT' not found in D:\sites\inherit.php on line 15

    so the answer for "are variable class extensions possible?" is: No.

    0 讨论(0)
提交回复
热议问题