Динамически создавать классы во время выполнения в 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);
Я создал пакет, который динамически создает классы/интерфейсы/черты характера... и хранит их в файле затем вы можете просто включить созданный файл, чтобы иметь возможность использовать свой класс