Подтвердить что ты не робот

Динамически генерировать классы во время выполнения в php?

Вот что я хочу сделать:

$clsName = substr(md5(rand()),0,10); //generate a random name
$cls = new $clsName(); //create a new instance

function __autoload($class_name)
{
  //define that instance dynamically
}

Очевидно, это не то, что я на самом деле делаю, но в основном у меня есть неизвестные имена для класса и основаны на имени, я хочу сгенерировать класс с определенными свойствами и т.д.

Я пробовал использовать eval(), но он дает мне возможность поместить личные и $this- > ссылки...

//редактировать

Хорошо, очевидно, что мой короткий и сладкий "вот что я хочу сделать" вызвал массовые распри и ужас среди тех, кто может дать ответы. В надежде получить реальный ответ я буду более подробно.

У меня есть структура проверки, использующая подсказки кода на сайте, который я поддерживаю. Каждая функция имеет два определения

function DoSomething($param, $param2){
   //code
}
function DoSomething_Validate(vInteger $param, vFloat $param2){
   //return what to do if validation fails
}

Я хочу добавить валидатор для первичных ключей в моей базе данных. Я не хочу создавать отдельный класс для КАЖДОЙ таблицы (203). Поэтому мой план состоял в том, чтобы сделать что-то вроде

function DoSomething_Validate(vPrimaryKey_Products $id){ }

Если __autoload будет генерировать подкласс vPrimaryKey и установить параметр таблицы в Products.

Счастлив сейчас?

4b9b3361

Ответ 1

Это почти наверняка плохая идея.

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

Что-то с сигнатурой командной строки, например:

./generate_classes_from_db <host> <database> [tables] [output dir]

Ответ 2

его смешно, на самом деле это одна из немногих вещей, где eval не кажется такой плохой идеей.

пока вы не можете гарантировать, что пользовательский ввод никогда не войдет в eval.

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

если вы знаете, что делаете, eval поможет вам в этом.

Тем не менее, на мой взгляд, вам намного лучше, когда вы не полагаетесь на тип-намеки на свою проверку, но у вас есть одна функция

DoSomething_Validate($id)
{ 
   // get_class($id) and other validation foo here
}

Ответ 3

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

Создать единый динамический класс

<?php
// Without properties
$myclassname = "anewclassname";
eval("class {$myclassname} { }";
// With a property
$myclassname = "anewclassname";
$myproperty = "newproperty";
eval("class {$myclassname} { protected \${$myproperty}; }";
?>

Пока вы должным образом избегаете своего текста, вы также можете добавить туда функцию.

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

Создание нескольких динамических классов

<?php

// Assumes $dbh is a pdo connection handle to your MySQL database
$stmt=$dbh->prepare("show tables");
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
$handle = null;
$classcode = '';
foreach ($result as $key => $value) {
    foreach ($value as $key => $value) {
        $classcode = "class {$value} { ";
        $stmt2=$dbh->prepare("DESC $value");
        $stmt2->execute();
        $result2 = $stmt2->fetchAll(PDO::FETCH_ASSOC);
        foreach ($result2 as $key => $value) {
            $classcode .= "public \${$value['Field']}; ";
        }
        $classcode .=  "}";
        eval($classcode);
    }
}

?>

Это будет динамически генерировать класс для каждой таблицы в базе данных. Для каждого класса также будет создано свойство, названное в честь каждого столбца.

Теперь было указано, что вы не должны этого делать. Пока вы контролируете, что происходит в eval, риск безопасности не является проблемой. НО - там, скорее всего, решение, имеющее больше смысла, если вы подумаете об этом достаточно глубоко. Я думал, что у меня есть идеальный вариант использования для динамического создания новых классов. Тщательное рассмотрение проблемы оказалось обратным.

Одно потенциальное решение - используйте stdClass для создания объектов, которые являются только контейнерами данных и не нуждаются в каких-либо методах.

Кроме того, как уже упоминалось, вы можете использовать script для ручного создания множества классов. В случае классов, отражающих ваши таблицы базы данных, вы можете использовать ту же логику, что и я, и вместо того, чтобы делать eval, пишите эту информацию в файл.

Ответ 4

Я думаю, что с помощью eval() это не надежное решение, особенно если ваш script или программное обеспечение будет распространяться среди разных клиентов. Общие хостинг-провайдеры всегда отключают функцию eval().

Я думаю об этом лучше:

<?php 

 function __autoload( $class ) {
      require 'classes/'.$class.'.php';

}

$class = 'App';
$code = "<?php class $class {
    public function run() {
        echo '$class<br>';  
    }
    ".'
    public function __call($name,$args) {
        $args=implode(",",$args);
        echo "$name ($args)<br>";
    }
}';

file_put_contents('classes/App.php' ,$code);

$a = new $class();
$a->run();

После завершения выполнения кода вы можете удалить файл, если хотите, я его протестировал, и он отлично работает.

Ответ 5

function __autoload($class)  {
    $code = "class $class {`
        public function run() {
            echo '$class<br>';  
        }
        ".'
        public function __call($name,$args) {
            $args=implode(",",$args);
            echo "$name ($args)<br>";
        }
    }';

    eval($code);
}

$app=new Klasse();
$app->run();
$app->HelloWorld();

Это может помочь создать класс во время выполнения. Он также создает прогон меток и общий метод для неизвестных методов Но лучше создавать объекты во время выполнения, а не классы.

Ответ 6

Использование eval() - действительно плохая идея. Это открывает большую дыру в безопасности. Просто не используйте его!

Ответ 7

Пожалуйста, прочитайте все остальные ответы о том, как это действительно очень плохая идея.

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


<?php
$clname = "TestClass";

eval("class $clname{}; \$cls = new $clname();");

var_dump($cls);