0

ユーザーがデータベースを介して任意の量の配列要素を設定できるコードがあります。キー名に基づいて関数をダックタイピングしていますが、すべてのキー名が呼び出すオブジェクトになるわけではなく、キーが静的な順序であるとは保証できません。コードは次のようになります。

$arr = get_arr_from_db();

foreach($arr as $key => $val){
    if($obj = new $key){
        unset($arr[$key]);

        $obj->give_data($arr);

        break;
    }
}

$obj->quack();

上記のコードは、死ぬため機能しません$obj = new $key。オブジェクトの作成に失敗したときに上記のループが停止しないようにする方法はありますか?

4

3 に答える 3

1

インスタンス化を試みる前に使用できclass_exists()ます。また、インスタンス化できなかった場合、try/catch ブロックはエラーをキャッチします。

foreach($arr as $key => $val){
  if(class_exists($key)){
    try {
        if($obj = new $key){
            unset($arr[$key]);

            if(method_exists($obj, 'give_data'){
                $obj->give_data($arr);
            }

            break;
        }
    } catch(Exception $e) {
        // do something with the exception
    }
  }
}
于 2012-12-27T01:03:43.313 に答える
1

シリアライズ

クラスの初期化と型チェックを処理するserializeunserializeを使用する方がはるかに簡単です。

例えば:

$person = new Person();
$person->firstname = 'Chuck';
$person->lastname = 'Jones';

$blob = serialize($person); // put blob in the database

インターフェイスのシリアル化/シリアル化解除

このアプローチに従う場合give_data()(たとえば、クラス プロパティがデータベース内の列名と一致するようにするため)、interfaceを指定する必要があります。インターフェイスは、呼び出しているクラスが利用可能な unserialize メソッドを持ち、期待どおりに動作することを保証します (以下の例ではファクトリ パターンを使用しています)。

<?php
interface ArraySerializable
{
    public static function createFromArray($array);
}

class Person implements ArraySerializable
{
    public static function createFromArray($array)
    {
        $temp = new self();
        $temp->firstname = $array['first_name'];
        $temp->lastname = $array['last_name'];
        return $temp;
    }
}

次に、テストしますclass_implements()

$class_name = 'Person';

if (class_exists($class_name)
    && in_array('ArraySerializable', class_implements($class_name))
){
    $person = $class_name::createFromArray(array(
        'last_name' => 'Jones',
        'first_name' => 'Chuck'
    ));

    var_dump($person);
}

これをより多くのクラスで使用するにはArraySerializable、それぞれのインターフェイスを実装するだけです。

これをゼロからロールバックしたくない場合は、Doctrineのようなフル機能の ORM を使用して、データベースを完全に抽象化できます。

于 2012-12-27T02:10:56.637 に答える
0

Reflectorクラスを使用することをお勧めします。

foreach($arr as $key => $val){
    $reflection = new ReflectionClass($key);
    if ($reflection->IsInstantiable()) {
        unset($arr[$key]);

        $obj = $reflection->newInstance();
        $obj->give_data($arr);

        break;
    }
}
于 2012-12-27T01:07:52.047 に答える