11

好吧,这在技术上是可行的,但这会破坏 MVC 架构吗?

我不确定控制器和模型之间是否建议使用这种类型的通信。我将使用一个简单的示例和两种方法来描述它:

选项 1(模型抛出异常并且控制器捕获它):

class Controller {
  private $model;

  public function save($data) {
     try {
         $this->model->save($data); 
     } catch (Exception $e) {  
         // handle exception
     }
  }
}

class Model {
  public function save($data) {
     // Call to internal function to save data in BD
     if (! $this->_save($data)) throw new Exception('Error saving data');
  }
}

选项 2(控制器完全处理异常):

class Controller {
  private $model;

  public function save($data) {
     try {
         if (! $this->model->save($data)) throw new Exception('Error saving data'); 
     } catch (Exception $e) { 
         // handle exception
     }
  }
}

class Model {
  public function save($data) {
     // Call to internal function to save data in BD
     if (! $this->_save($data)) return false;
  }
}

**

一些回应后编辑:

**

这些是根据您的建议解决问题的其他方法。我希望不要把事情弄得太复杂。

选项 3(模型完全处理异常,正如 Ray 所说。KingCrunch 还建议在模型中更好地做到这一点)

class Controller {
  private $model;

  public function save($data) {

     if (! $this->model->save($data)) {
         // possible action: redirect to the form with an error message
     }

  }
}

class Model {
  public function save($data) {
     try {
         if (! $this->_save($data)) throw new Exception('Error saving data'); 
     } catch (Exception $e) { 
         // handle exception
         return false;
     }
     return true; 
  }
}

选项 4(控制器获取模型抛出的自定义子异常,如 shiplu.mokadd.im 所说。)

class Controller {
  private $model;

  public function save($data) {
     try {
         $this->model->save($data); 
     } catch (Exception $e) {  
         if ($e instanceof ValidationException) {
            // handle validation error
         }
         elseif ($e instanceof DBStorageException) {
            // handle DB error
         }
     }
  }
}

class Model {
  public function save($data) {
     if (! $this->_validate($data)) {
        throw new ValidationException ('Validation error');
     }
     if (! $this->_save($data)) {
        throw new DBStorageException ('Storage error');
     }
  }
}
4

3 回答 3

9

模型可以抛出异常并且控制器或视图应该捕获它。否则你永远不知道那里的一切是否正常。所以使用第一个选项。但请确保您抛出对控制器和 View 有意义的正确抽象的异常

为了说明上面的粗线,请参见模型内部使用的这两个 throw 语句。

 throw new Exception('SQL Error: '.$mysqli->error()); // dont use it
 throw new DuplicateFieldException('Duplicate username'); // use this

第二个示例没有显示内部错误。相反,它隐藏了它。控制器永远不应该知道里面发生了什么。

在您的代码中,您将单个模型绑定到单个控制器。控制器不代表单个模型。它使用模型。它可以使用任意数量的模型。所以不要将单个模型与带有变量的控制器捆绑在一起private $model

于 2013-01-08T22:21:47.177 回答
2

绝对是第一选择。一些单词:

  • 控制器的工作是……嗯,控制。这意味着,它应该小心,至少会出现一个有用的错误消息。应用程序的其他部分可能会在它们能够处理异常情况之前执行此操作。这包括模型本身:如果它能够处理它,它应该这样做。

  • save()意思是“保存”。不要滥用状态信息的返回值。当方法不能提供时,save()它是一个例外,并且当方法不必给你一些东西时,它不应该给你一些东西。

于 2013-01-08T22:19:09.913 回答
1

我更喜欢选项3。

模型应该捕获异常,尝试解决它,如果不将其渗透到控制器,但前提是它是控制器可以解决和恢复的东西。在这种情况下,(某种 DB 保存失败)在模型返回中捕获它false应该足以解决保存错误,并为控制器提供足够的信息来知道保存时出了什么问题。

控制器不需要担心模型如何实现保存的实现细节。

于 2013-01-08T22:18:19.780 回答