Вот что я хочу сделать:
$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 и задает параметр table для Products.
Счастлив теперь?
Это почти наверняка плохая идея.
Я думаю, что ваше время было бы лучше потрачено на создание сценария, который создавал бы для вас определения классов и не пытался это делать во время выполнения.
Что-то с такой командной строкой, как:
./generate_classes_from_db <host> <database> [tables] [output dir]
это смешно, на самом деле это одна из немногих вещей, где eval не кажется такой плохой идеей.
до тех пор, пока вы не можете гарантировать, что пользовательский ввод никогда не войдет в eval.
у вас все еще есть недостатки, например, когда вы используете кеш байт-кода, который не будет кэшироваться и т. д., но проблемы безопасности eval в значительной степени связаны с тем, что пользователь вводит значение в 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()
это не надежное решение, особенно если ваш скрипт или программное обеспечение будет распространяться среди разных клиентов. Общие хостинг-провайдеры всегда отключают функцию 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();
После завершения выполнения кода вы можете удалить файл, если хотите, я его протестировал, и он отлично работает.
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();
Это может помочь создать класс во время выполнения. Он также создает метод metor и метод catchall для неизвестных методов. Но лучше создавать объекты во время выполнения, а не для классов.
Использование eval () – действительно плохая идея. Это открывает большую дыру в безопасности. Просто не используйте его!
Пожалуйста, прочитайте все остальные ответы о том, как это действительно очень плохая идея.
Как только вы это понимаете, вот небольшая демонстрация о том, как вы могли, но не должны этого делать.
<?php $clname = "TestClass"; eval("class $clname{}; \$cls = new $clname();"); var_dump($cls);