36

これが私がやりたいことです:

$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()を使用してみましたが、privateおよび$this->参照に適合しています...

//編集

わかりました、明らかに私の短くて甘い「これが私がやりたいことです」は答えを提供することができるかもしれない人々の間で大規模な争いと驚愕を引き起こしました。実際の答えを得ることを期待して、私はより詳細になります。

自分が管理しているサイトにコードヒントを使用した検証フレームワークがあります。各関数には2つの定義があります

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に設定する場合。

今幸せです?

4

10 に答える 10

13

これは古い質問であり、うまくいく答えがあることは知っていますが、元の質問に答えるいくつかのスニペットを提供したかったので、回答を検索したときのように誰かがここにたどり着いた場合、より拡張されたソリューションを提供すると思いますこの問題に。

単一の動的クラスを作成

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

?>

これにより、データベース内の各テーブルのクラスが動的に生成されます。クラスごとに、各列にちなんで名付けられたプロパティも作成されます。

これを行うべきではないことが指摘されています。評価で何が起こっているかを制御する限り、セキュリティのリスクは問題になりません。しかし、十分に深く考えれば、より理にかなった解決策がある可能性が高いです。新しいクラスを動的に作成するための完璧な使用例があると思いました。問題を注意深く調べたところ、そうではないことが証明されました。

考えられる解決策の 1 つ - stdClass を使用して、単なるデータ コンテナーであり、メソッドを必要としないオブジェクトを作成します。

また、前述のように、スクリプトを使用して多数のクラスを手動で生成することもできます。データベース テーブルをミラーリングするクラスの場合、上記と同じロジックを使用して、eval を実行する代わりに、その情報をファイルに書き込むことができます。

于 2013-03-22T20:39:01.040 に答える
13

面白いことに、これは eval がそれほど悪い考えに見えない数少ないことの 1 つです。

ユーザー入力が評価に入力されないことを保証できる限り。

コードがキャッシュされないなどのバイトコードキャッシュを使用する場合などの欠点はまだありますが、eval のセキュリティの問題は、eval にユーザーが入力したり、間違ったスコープになってしまうことにかなり関連しています。

自分が何をしているのかわかっている場合は、 eval がこれに役立ちます。

とはいえ、私の意見では、検証のためにタイプヒントに依存しない方がはるかに優れていますが、関数は1つしかありません

DoSomething_Validate($id)
{ 
   // get_class($id) and other validation foo here
}
于 2010-06-03T13:48:57.740 に答える
5

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

コードの実行が終了したら、必要に応じてファイルを削除できます。テストしたところ、完全に機能します。

于 2014-08-30T11:36:45.153 に答える
4

eval()を使用することは本当に悪い考えです。それは大きなセキュリティホールを開きます。使用しないでください!

于 2009-07-29T23:29:34.573 に答える
3
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();

これは、実行時にクラスを作成するのに役立つ場合があります。また、メソッドの実行と不明なメソッドのキャッチオール メソッドも作成しますが、クラスではなく、実行時にオブジェクトを作成することをお勧めします。

于 2012-03-17T21:18:03.253 に答える
2

これはほぼ間違いなく悪い考えです。

実行時にクラス定義を作成するのではなく、クラス定義を作成するスクリプトを作成する方が時間がかかると思います。

次のようなコマンドライン署名のあるもの:

./generate_classes_from_db <host> <database> [tables] [output dir]
于 2009-07-29T23:27:16.110 に答える
1

これが本当に非常に悪い考えである方法について、他のすべての人の回答を読んでください。

それを理解したら、これを行う方法についての小さなデモを示しますが、そうすべきではありません。


<?php
$clname = "TestClass";

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

var_dump($cls);
于 2009-07-29T23:36:22.203 に答える