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 回答