Динамически создавать классы во время выполнения в 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-> references...

/ / edit

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

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

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.

теперь счастлив?

8 ответов


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

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

что-то с подписью командной строки, например:

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

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

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

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

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

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

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

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

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

<?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 для создания объектов, которые являются просто контейнерами данных и не нуждаются в каких-либо методах.

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


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


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

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


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


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

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


<?php
$clname = "TestClass";

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

var_dump($cls);

Я создал пакет, который динамически создает классы/интерфейсы/черты характера... и хранит их в файле затем вы можете просто включить созданный файл, чтобы иметь возможность использовать свой класс

пакет:https://packagist.org/packages/kanel/enuma