Расширения классов переменных переменных в PHP - возможно ли это? - PullRequest
4 голосов
/ 20 ноября 2008

Возможно ли что-то подобное в PHP?

$blah = 'foo1';

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

class foo1 {
    //...
}

Это дает ошибку.

Я хочу динамически установить $ blah, чтобы я мог расширить любой класс, какой захочу.

Редактировать: Причина, по которой я хотел сделать это, потому что я хотел использовать функцию из другого класса в связанном классе. В конце концов это было бы что-то вроде:

Final extends foo1 extends foo2 extends foo3 extends foo4 extends parent { ... }

В конце я решил создать экземпляр другого класса в классе и использовать его. Не самый лучший вариант, потому что они оба из двух классов, но это будет использоваться не так часто, так что пока это будет работать.

Ответы [ 8 ]

15 голосов
/ 20 ноября 2008

Вы предполагаете, что здесь php выполняется сверху вниз, но это не совсем так:

<?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

Теперь, хотя вы можете условно создавать классы:

<?php

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

Вы не можете создать экземпляр во время выполнения из переменной:

<?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

Есть способ сделать это с Eval, но вы действительно не хотите туда идти:

<?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!

Однако здесь есть более важный вопрос:

Какого черта вы хотите расширить другой класс во время выполнения

Любой, кто использует ваш код, захочет удержать вас и сбить вас за это.

(В качестве альтернативы, если вы увлекаетесь поркой, сделайте этот пробный трюк)

2 голосов
/ 01 октября 2012

Я знаю, что этот вопрос задавался очень давно, но ответ относительно прост.

Предполагая, что вы хотите расширить класс foo, если класс foo существует, или панель классов, если его нет, вы должны использовать:

if(!class_exists('foo')) {
    class foo extends bar {
        function __construct() {
            parent::__construct();
        }
    }
}

class myclass extends foo{
    //YOUR CLASS HERE
}
2 голосов
/ 20 ноября 2008

Если у вас не слишком много значений для $ blah, вы можете расширить каждое из них в отдельном файле, тогда require_once "classes/foo_$blah.php"

В противном случае, вы застряли с решением eval() ... удачи вам с этим ...:)

2 голосов
/ 20 ноября 2008

Я предполагаю, что это для простоты обслуживания, верно? Продление класса во время выполнения действительно довольно безумно.

class SuperClassOne { /* code */ }
class SuperClassTwo { /* code */ }

class IntermediateClass extends SuperClassOne { /* empty! */ }

class DescendantClassFoo extends IntermediateClass{ }
class DescendantClassBar extends IntermediateClass{ }
class DescendantClassBaz extends IntermediateClass{ }

Затем, когда вы хотите изменить все свои DescendantClass* классы, вам просто нужно изменить то, что расширяет IntermediateClass:

class IntermediateClass extends SuperClassTwo { }
2 голосов
/ 20 ноября 2008

Я не понимаю, как это было бы особенно полезно, но чтобы ответить на ваш вопрос ... нет. Нет никакого способа сделать это динамически, потому что сгенерированный класс должен быть создан до оценки переменной (если это имеет смысл).

Проще говоря: класс должен существовать, прежде чем код может быть правильно выполнен.

1 голос
/ 28 января 2015

Используя перегрузку PHP , вы можете достичь этого в определенной степени.

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

Я использую этот шаблон внутри модуля Drupal для предварительной выборки данных из кэша .

1 голос
/ 27 мая 2011

Я тестировал что-то с определениями и лаем:

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

вывод:

Неустранимая ошибка: класс 'INHERIT' не найден в D: \ sites \ inherit.php в строке 15

поэтому ответ на вопрос "возможны ли расширения класса переменных?" это: №

0 голосов
/ 02 ноября 2009

Вы должны были попробовать $$

$blah = 'foo1';
class foo2 extends $$blah {
    //...
}

class foo1 {
    //...
}
...