之前团队留下的模型代码都是这样的:
public function getcount($where){//$where是数组,严格对应DB字段!
if(!empty($where)){
$db->where($where);
}
$db->from($tablename);
return $db->count_all_results();
}
public function edit($tid,$data){//$data是数组,严格对应DB字段!
$db->where('tid', $tid);
return $db->update($tablename, $data);
}
当我在控制器里调用MODEL的时候,要严格按照数据库schema来拼装参数。
MODEL里这样写这样的纯粹的增删改查有什么优点?
验证部分究竟应该放在哪里比较好?
请阐明其中的道理和厉害关系。
之前可能有人看的太快导致的误解,上述代码的model里面那个empty并不算真的判断,关于$where参数,是需要严格按照数据库对应的字段拼装,而model里并没有任何判断,严重依赖控制器喂给它正确的参数。
项目经理铁定要求在控制器处理验证,所以现在的控制器里有数量可观的巨型函数(需要调用model的地方都超过150行了),而且格式基本近似。
举个例子,现在的情况是:
view提交表单到controller,在那里验证表单,呼叫model,并为model拼装数组参数(如同上面代码里那样)。
看到后来新的答案里有些说的情况比较模糊,比如“复杂逻辑”这样还是没法明确。所以,我再细化一下问题:
现在的model里仅仅是转发了一下sql的增删改查的基本操作,在控制器里调用这些model的时候,我必须严格根据数据库里的字段名来拼装$data数组,这就基本等同于没有model,还不如控制器里直接拼sql算了。
首先,你们团队的代码是正确的,输入验证是放在model层。model是与数据交互的,按照“与谁关系最密切就与谁处理”的原则,数据验证应该由model层处理,controller只是起到一个转发的作用,与逻辑数据有关的不应该放在这里面。
关于道理和厉害关系:
说实话,这个没啥理论,就是一辈辈的开发者们经验所得。你可以将验证放在controller里面,然后开发一个大型应用试一下就知道了。
跟设计模式差不多,为什么要这样设计?完全就没有道理,完全是无数次实验之后得出的结论。然后这些不好的地方自然就成了好的道理。
以后遇到这种没有定性的问题,你自己实验一下,自然就知道哪里放哪里好了。
正所谓知道了什么不好,才真正的知道什么才是好。人生亦是如此
我们团队用的Java,现在的验证方法是这样的:
比如User
, 使用各种JSR303在实体上搞好校验规则和校验message,封装好check
方法(这个是最基础的,不管怎么样都需要验证的,一般我们使用的是Hibernate-Validator实现),如果类型和逻辑比较多,还可以衍生出updateCheck()
,saveCheck()
,如果校验没有通过就抛出参数错误异常;我在做的过程中其实想到这一点没有必要另外些check方法,完全可以使用JSR303的group分组来实现不同业务的需求验证(这点没有具体实践,只是现在有这么一个想法)
然后在controller那里注解调用对应的check方法作为验证就行了,验证方法如果抛出异常了,直接在catch里面做相应的处理返回.
验证代码应该写在服务层
那么这里就要对mvc解析一下
v层由于变动频繁,而又非服务端程序员必理层,故此完全可以独立出来,以配置方式分发。
m层是数据层,那就单纯处理数据就得了,不要添加其他没必要的处理,导致混乱。
c层是调度层,对用户传递过来的url作对应处理,这里跟权限有关,登陆和没登陆的操作。
那么这里少了一层,就是逻辑层logic。建议添加l层
l层处理逻辑,提供服务,提供关闭和开放的决定。
而验证建议使用c层的权限判断,而权限判断是一个服务,让l层提供。
这样设计的好处不少
v层对外,只提供配置文件,让有关程序员,只配置文件即可。
其次m层可以独立出来一个专用服务器,也可安排专门处理这块的程序员负责。
c层处理用户调度,掌握业务层和用户体验的程序员最适合。
l层实际就是服务层,链接业务层和数据层,版本控制,启用和关闭服务。
对新来的同事,验证服务有问题,可以让他重写一个验证服务,不必重写原来的验证的服务。这种修改方式,应该是养成习惯,不修改,只增加。
对于楼主要解决的验证写在controller还是model里,这个问题,取决于架构问题。
如果就是mvc,那么是否有不同角色权限,如果不是,可以选择新建一个基础c,里面配置一个用户验证。如果有不同角色权限,完全可以继承这个基础c,重写即可。
建议在c层验证,个人认为,用户进来,进入调度范围,就必须要正确到达目的地,否则,我不知道调度的作用为何。
如果没有设计缺陷,就放在c层验证吧,概念更清晰一些。
c层验证,l层逻辑