【问题标题】:PHP - Error handling issuePHP - 错误处理问题
【发布时间】:2012-12-27 00:54:19
【问题描述】:

我有一些代码,用户可以通过数据库设置任意数量的数组元素。我是基于键名的鸭子类型函数,但并非所有键名都是要调用的对象,我不能保证键可以按静态顺序排列。代码类似这样:

$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 会死。有什么办法可以防止上述循环在对象创建失败时死掉?

【问题讨论】:

    标签: php error-handling duck-typing


    【解决方案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
        }
      }
    }
    

    【讨论】:

    • 你很接近,但我还需要验证该方法是否存在于类中。谢谢你让我走上正轨。
    • @user1813212 没问题,添加到回答中。 try/catch 也会捕获丢失的方法错误。
    【解决方案2】:

    序列化

    使用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 来完全抽象数据库。

    【讨论】:

      【解决方案3】:

      最好使用Reflector 类:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-31
        • 2016-02-26
        • 2010-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-18
        • 2017-07-20
        相关资源
        最近更新 更多