Расширения классов переменных переменных в PHP - возможно ли это?

Возможно ли в PHP что-то вроде следующего?

$blah = 'foo1';

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

class foo1 {
    //...
}

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

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

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

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
5
0
7 316
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

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

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

Мое чувство было таким же. Но с PHP мало ли ... ;-)

Tomalak 20.11.2008 10:36

Как сказал Кент Фредрик, это возможно. Не красиво, но возможно.

Darryl Hein 20.11.2008 19:49
Ответ принят как подходящий

Вы предполагаете, что здесь 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!

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

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

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

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

В идеальном мире люди не хотели бы этого делать. Но это не идеальный мир. Я искал это, потому что застрял в Joomla, меняя родительский класс для определения новых «элементов» между версией 1.5.x и более поздними версиями. Мой подкласс не должен быть другим, и мне не нужны разные базы кода, поэтому я хочу иметь возможность наследовать от разных классов в соответствии с версией Joomla. Вот почему.

user185631 26.07.2012 20:35

Кажется, что использование Generics невозможно с PHP, к сожалению, я подумал о том, чтобы взломать его таким образом!

Ziyan Junaideen 05.05.2013 06:10

@ user185631 Пришел сюда по той же причине.

mavrosxristoforos 15.10.2013 21:32

Какого черта вам нужно расширять другой класс во время выполнения? Тестирование, имитируйте статический метод :(

Abdillah 27.06.2018 12:43

@Abdillah PHP - неподходящий инструмент для этой работы. Причина, по которой добавляется eval, представляет непостижимые уровни рисков для эксплойтов безопасности. Тем не менее, вы все еще можете это сделать, но не обманывайте себя, что то, что вы делаете, в любом случае «хорошо», и убедитесь, что у вас нет соблазна использовать этот код в своем производственном стеке, просто в качестве меры предосторожности. .

Kent Fredric 16.05.2019 04:13

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

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

Плохое использование однострочных комментариев. Закрывающие скобки} закомментированы!

luiscubal 04.12.2009 01:38

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

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

Это не работает. См. stackoverflow.com/questions/23726288/…

Franz Holzinger 20.02.2020 14:22

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

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

class foo1 {
    //...
}

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

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

вывод:

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

Итак, ответ на вопрос «Возможны ли расширения классов переменных?» нет.

однако вы можете создать класс, который может наследовать от чего угодно, унаследовав класс MultipleInheriter, у которого есть список классов в массиве, а затем он вызывает методы с __call в статическом контексте, поэтому $ this внутри методов переводится в текущий класс. Только общедоступные МЕТОДЫ будут работать, так что это действительно поддельное наследование. Затем вы должны вызвать метод extend () и добавить класс в список.

SparK 03.11.2011 21:35

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

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

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

class myclass extends foo{
    //YOUR CLASS HERE
}

Эта идея может сработать ... некрасиво, если есть, скажем, 5 возможных классов, от которых вы, возможно, захотите продолжить.

Darryl Hein 04.10.2012 10:02

Согласен, но из одного из ваших комментариев похоже, что вы разрабатываете для Joomla. Я предполагаю, что класс, который вы пытаетесь расширить, либо доступен, либо нет, в зависимости от версии Joomla, поэтому я предполагаю, что возможные классы будут ограничены двумя или около того. К сожалению, нет простого способа (который я знаю) использовать переменную вместо имени класса, т.е. вы не можете написать class myclass extends $ classvar {}, так что это лучшая альтернатива. Но вы правы ... 5+ возможных классов, это будет некрасиво!

whizzkid 04.10.2012 23:29

Нет необходимости добавлять __construct в foo.

Kjeld 15.06.2018 22:42

Используя Перегрузка 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 для предварительная выборка данных из кеша.

Другие вопросы по теме