【问题标题】:Input validation in MVCMVC 中的输入验证
【发布时间】:2015-10-20 11:49:45
【问题描述】:

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

【问题讨论】:

    标签: codeigniter model-view-controller


    【解决方案1】:
    1. 关于在 Controller 中进行输入验证 答。是的,这是大多数 MVC 中普遍接受的做法。然而,在过去的几年中,由于 AJAX 框架的出现和 JavaScript 的更多采用,许多 UI 验证都是在 UI 本身完成的(称为客户端验证)。这些通常显示为 javascript 警告框,除非用户修复这些错误,否则不允许用户继续操作。所以,我会说控制器/视图助手实际上是完成验证的地方,但您应该在可行的情况下考虑客户端验证。它还可以节省您前往服务器的次数。

    2. 如果您公开与 SOAP/REST 相同的功能 答。现在,您可以注释相同的控制器方法以使它们作为 Web 服务端点工作。因此,您的控制器既可以为基于 Web 的请求提供服务,也可以为 SOAP/REST 请求提供服务。 但要注意一点——你的表单bean/支持bean应该设计得很好。我见过将休眠模型对象用作表单支持对象的代码。这使得当您从表单支持对象生成 WSDL 时变得很棘手,因为休眠模型对象可能具有许多链接实体,并且最终在请求/响应中具有非常复杂的 xml 结构。 但是,如果您将支持 bean 设计为细粒度的,即没有复杂的对象,那么您应该可以轻松地将现有的控制器/控制器方法用作 SOAP/REST 的 Web 服务端点。

    3. 关于模型层内部的验证 答。您可以使用此拇指规则来确定放置哪些验证的位置 -
      • 应在模型/服务中进行业务验证
      • 在客户端不可行的复杂客户端验证应该在控制器/视图助手中进行
      • UI 验证(格式化/空检查)应通过客户端/javascript 验证进行
    4. 关于控制器功能与模型/服务之间的一对一关系 答。没关系。请记住让一个控制器方法与其各自的模型方法对话。如果需要多个模型来为请求提供服务,则该模型方法应充当来自多个模型的信息的聚合器,即控制器应联系其主模型,而主模型应联系其他模型。

    【讨论】:

    • 我明白你的意思,但我没有什么困惑。我们可以依赖客户端验证吗?客户端始终可以通过禁用 javascript 或使用 http 请求标头来绕过验证。如果一个模型调用另一个模型,那么是否违反了 SOC,因为模型的凝聚力降低了?您能否提供一些链接或示例来描述使控制器与多个模型通信的缺陷。抱歉问了太多问题。
    • 是的,您可以依赖客户端验证。基本上,您仅在所有客户端验证通过时才提交表单。如果您查看所有主要网站,它们都严重依赖 javascript。只有少数有非 JavaScript 版本。关于模型调用模型,为业务逻辑提供服务调用服务是一种普遍接受的做法。我并不是说 DAO 调用 DAO。 DAO 应该专门从它们各自的服务中调用。最后,我参与过许多基于 Web 的项目,我的答案都是基于此。我手头没有参考网站列表。
    • @KrrishRaj 客户端验证可以依赖,但可能不,也可能不应该完全消除后端验证的需要。模型调用模型,IMO,显然违反了 SOC。另一方面,在我看来,让控制器使用多个模型似乎就是您创建 SOC 的方式。 CodeIgniter 将允许您在另一个模型中加载模型。您最容易陷入这种方式的陷阱是依赖问题。特别是,循环引用都非常容易构造。
    • @KrrishRaj 我看到了你的邮件......从 javabrahman 邮寄到 hotmail 时遇到了一些问题。你能用非hotmail id给我发一封邮件吗,我会在这个周末之前回复你的邮件。
    【解决方案2】:

    这是一个好习惯吗?根据我的经验,是的。

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

    一个粗略的伪代码“仪表板”控制器可能如下所示:

    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/admins 打开,用户CRUD 使用baseurl/dashboard/users 打开。因为它们中的每一个共享相同的类,所以所有/许多这些页面所需的代码(如验证)可以在构造函数和/或私有方法中实现。您可能已经知道这一切。请记住,AJAX 响应者也可以使用相同的技术驻留在控制器中。

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

    【讨论】:

      猜你喜欢
      • 2011-04-08
      • 2010-09-14
      • 1970-01-01
      • 2020-12-03
      • 2011-04-23
      • 2016-04-15
      • 1970-01-01
      • 1970-01-01
      • 2011-07-29
      相关资源
      最近更新 更多