2015-10-20 241 views
0

我需要一些关于MVC设计的帮助。 MVC和CODEIGNITER的大部分教程都是在控制器中进行输入验证。这是一个好习惯吗?
假设我们实现REST或SOAP API,那么我们将拥有不同的控制器,并且对于所有这些控制器,我需要复制我的代码。稍后,如果任何验证规则发生更改,它将会波及所有控制器。是不是所有的验证都应该在Model而不是Controller中?
我还想问一件事。当我试图保持我的功能尽可能紧密时,我正在获得模型和控制器功能之间的一对一关系。没关系,或者我做错了什么?MVC中的输入验证

回答

0
  1. 关于在控制器中进行输入验证 Ans。是的,这是大多数MVC普遍接受的做法。但是,在过去几年中,由于AJAX框架的出现以及JavaScript的更多采用,许多UI验证都是在UI本身完成的(称为客户端验证)。这些通常显示为JavaScript警报框,并且不允许用户继续前进,除非他修复了这些错误。所以,我会说控制器/视图助手实际上是验证完成的地方,但您应该考虑在可行的情况下进行客户端验证。它还可以节省您前往服务器的时间。

  2. 如果您公开的功能与SOAP/REST Ans相同。现在,您可以注释相同的控制器方法,使其作为Web服务端点工作。因此,您的控制器可以同时处理基于Web的请求和SOAP/REST请求。 但请注意一点 - 你的形态豆/支撑豆应该设计得很好。我已经看到了代码,其中hibernate模型对象被用作表单支持对象。由于hibernate模型对象可能有许多链接的实体,并且在请求/响应中以非常复杂的xml结构结束,所以当您从表单支持对象中生成WSDL时,这会非常棘手。 但是,如果你设计的支持bean是细粒度的,即没有复杂的对象,那么你应该放心使用现有的控制器/控制器方法作为SOAP/REST的Web服务端点。

  3. 关于模型层内的验证 Ans。您可以使用此经验法则来确定在何处放置其验证 -
    • 业务验证应在模型/服务发生
    • 复杂的客户端验证,这是不是在客户端是可行的,应在控制器/视图助手发生
    • UI验证(格式化/空检查)应通过客户端/ JavaScript的验证
  4. 关于控制器和模型/服务 答的功能之间以一对一的关系发生。没关系。只要记住有一个控制器方法与其各自的模型方法交谈。如果需要多个模型来为请求提供服务,那么该模型方法应该充当来自多个模型的信息聚合器,即控制器应该联系其主要模型,并且主要模型应该联系其他模型。
+0

我明白了你的观点,但我很少有混淆。我们可以依靠客户端验证吗?客户端可以通过禁用JavaScript或通过使用http请求标头来绕过验证。如果一个模型调用另一个模型,那么不会违反SOC,因为模型的凝聚力会降低?你能否给我提供一些链接或例子,描述使控制器与多个模型交谈的缺陷。对于提出太多问题抱歉。 –

+0

是的,您可以依靠客户端验证。基本上只有当所有客户端验证通过时才提交表单。如果你看看所有主要的网站,他们严重依赖于JavaScript。只有少数人拥有非JavaScript版本。关于模型调用模型,它是业务逻辑的服务调用服务的普遍接受的实践。我不是说DAO打电话给DAO。应仅从各自的服务中调用DAO。最后,我曾在许多基于网络的项目中工作,我的答案是基于此。我没有参考网站的手头清单。 –

+0

@KrrishRaj客户端验证可以依赖,但可能不会,也可能不应该完全消除对后端验证的需求。模型调用模型,IMO显然违反了SOC。另一方面,有一个控制器使用多个模型在我看来是你如何创建SOC。 CodeIgniter将允许您在另一个模型中加载模型。最容易陷入这种方式的陷阱是一个依赖性问题。特别是,循环引用都很容易构建。 – DFriend

0

这是一个很好的做法吗?根据我的经验是的。

有一点要记住,任何给定的控制器都可以显示多个不同的页面。例如,考虑一个“仪表板”,它可能有多个任务,每个任务都需要自己的页面。

粗略伪codeish“仪表板”控制器可能是这样的:

class Dashboard extends CI_Controller { 
    public function __construct(){ 
    parent :: __construct(); 
    $this->load->helper(array('form', 'url')); 
    $this->load->library('form_validation'); 
    $this->load->model('somemodel_model'); 
    } 
    public function index(){ 
    //displays a task selection page with links to various tasks 
    } 
    public function admins(){ 
    //some kind of interface to display and edit admin level users 
    } 
    public function users(){ 
    //CRUD for dashboard users 
    } 
} 

与此控制器的任务选择页面打开与baseurl/dashboard,管理员联系与baseurl/dashboard/adminsbaseurl/dashboard/users用户CRUD页面。因为每个这些共享相同的类,所有/许多这些页面所需的代码(如验证)可以在构造函数和/或私有方法中实现。你可能已经知道了这一切。请记住,AJAX响应者也可以使用相同的技术驻留在控制器中。

关于保持验证规则DRY并缓解更改规则所需的工作CI可以将一组规则存储在配置文件中,以便在多种情况下轻松重复使用。 Read about it.