V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wu1990
V2EX  ›  PHP

到底是应该在 Model 里写 function getByEmail 还是在 Controller 里调用->where('email',"[email protected]")?

  •  
  •   wu1990 · 2017-06-17 13:00:19 +08:00 · 4303 次点击
    这是一个创建于 2718 天前的主题,其中的信息可能已经有所发展或是发生改变。

    下面的(伪)代码都基于 Eloquent ORM。

    当然不是完全在 Controller 里写,Controller 和 Model 中间还有一层是负责业务的( Service/Logic ),调用都在 这一层里。

    标题只是为了简单描述

    一直往 Model 里写 getByxxx 会导致 Model 的方法越来越多…

    有人会说写一个

    function getByConds(array $conds) () {
    	if(isset($conds['email'])) {
    		$query->where('email', $conds['email']);
    	}
    	if(isset($conds['xxx'])) {
    		$query->where('xxx', $conds['xxx']);
    	}
    	return $query->get();
    }
    

    然后再里面判断 ,那这样和 ->where('email',"[email protected]") 还有区别吗,->where 可以理解为当做也是传递条件而已吧?

    function ($column1, $column2, $orderColumn, $orderDirection) {
    }
    // 是不是等同于
    $query->where('column1', 'value1')
    	->where('column1', 'value2')
    	->orderBy('orderColumn', 'desc')
    	->get();
    

    我觉得应该在 Model 里写 scope 把常用的查询条件统一管理即可。文档: https://docs.golaravel.com/docs/5.4/eloquent/#local-scopes

    Model 里增加:

    functoin scopeVisible($query, $userId) {
    	return $query->whereRaw('passed = 1 OR user_id = ?', [$userId]);
    }
    functoin scopeDefaultSort($query) {
    	return $query->orderBy('weight', 'desc')->orderBy('update_time', 'desc');
    }
    // 然后查询的时候:
    $query->visible($user->id)->defaultSort();
    

    还有,要不要再 Model 里写 create/add 方法,我觉得在 Service/Logic 层统一处理就可以了,没必要放到 Model 里

    <?php
    class User
    {
    	public static function add($email, $nickname, $password) {
    		$user = new User();
    		$user->email = $email;
    		// ...
    		$user->save();
    	}
    }
    User::add('email', 'nickname', 'password');
    
    

    或者动态方法……

    class User
    {
    	public function add($email, $nickname, $password) {
    		$this->email = $email;
    		// ...
    		$this->save();
    	}
    }
    $user = new User();
    $user->add('email', 'nickname', 'password');
    

    不知道大家怎了理解的…

    27 条回复    2017-06-18 21:49:08 +08:00
    mrcn
        1
    mrcn  
       2017-06-17 13:23:52 +08:00
    我觉得应该在控制器直接调用比较好。

    如果在 Model 加一个的话相当于只是把 where('email',a)替换成了 whereEmail(a)

    没什么意思。
    littleylv
        2
    littleylv  
       2017-06-17 13:39:50 +08:00
    ORM 已经都封装好了,就直接 Controller 里调->where 就好了
    k9982874
        3
    k9982874  
       2017-06-17 13:43:46 +08:00 via iPhone
    我觉得应该在 controller 里写 getByMail。
    然而个人认为真正正确的做法应该包装 User 类,解藕和复用。
    wingoo
        4
    wingoo  
       2017-06-17 13:44:47 +08:00   ❤️ 3
    新建 service/logic 层
    model 和 controller 中不涉及业务代码
    alwayshere
        5
    alwayshere  
       2017-06-17 13:48:38 +08:00
    function getUserInfoByAttr(){}
    devinww
        6
    devinww  
       2017-06-17 13:55:52 +08:00
    controller 是响应用户操作,调用 service,service 层是写业务代码的
    littleylv
        7
    littleylv  
       2017-06-17 14:12:56 +08:00
    @wingoo #4
    @devinww #6
    一般的 MVC 框架里,service 层是怎么分布的?目录结构或者调用方式是怎样的?
    有没有什么例子可以提供一下。先谢谢了。
    wingoo
        8
    wingoo  
       2017-06-17 14:21:13 +08:00
    目录结构可以和 model 同级, 调用就是 new 一个调是了
    pantingwen
        9
    pantingwen  
       2017-06-17 14:28:17 +08:00
    ORM 优有,直接调用就好了, 如果调用代码比较多,后续还会有其他的地方也会这样调用再封装
    zonghua
        10
    zonghua  
       2017-06-17 14:45:16 +08:00
    @wingoo 什么样才算算业务功能的语句
    fortunezhang
        11
    fortunezhang  
       2017-06-17 14:46:34 +08:00
    如果只是简单的查,简单的查,简单的查,那就直接在 controller 里面 where 就行,如果复杂的查,比如用户你要得到用户详细信息,其中还包括用户的发布文章的数量,就在 model 层去做。新增、修改、删除尽量在 model 里面做。
    我是这样做的。不对,请轻喷
    wingoo
        12
    wingoo  
       2017-06-17 14:56:39 +08:00
    @zonghua 这样说吧, model 是可用工具生成的, 里面只是生成的代码
    controller 中只有接收数据和返回, 中间都调用 service 里的方法
    Immortal
        13
    Immortal  
       2017-06-17 15:20:53 +08:00
    那大佬们 顺便插问一句
    现在的 MVC 具体到代码 其实是 Controller Service/Logic Model View 四层 只是我们平时说的时候把 Service 隐式的归到了 Model 吧?
    还有那如果一般数据校验什么的都放到 Service 么,Controller 只是个接参数然后传参?
    wu1990
        14
    wu1990  
    OP
       2017-06-17 15:28:39 +08:00
    @Immortal controller 决定返回的数据格式或者页面模板。
    neoblackcap
        15
    neoblackcap  
       2017-06-17 15:29:03 +08:00
    @Immortal controller 本身是控制业务流程跳转,可以理解成是流水线上的分支开关,model 本身是对应到流水线上的其中一步的业务,不是对应代码的 Model,MVC 里面的 Model 是领域模型,View 就是表象而已,好比你在监控台上看到流水线上每一步的状态是一个绿灯。
    Immortal
        16
    Immortal  
       2017-06-17 15:32:09 +08:00
    @wu1990 那对于纯粹的 api2 个不同的 api,需要返回不同格式的数据格式,但我可以从一个 service 的方法里获取源数据,那么数据格式的整理都是在 controller 还是 service 分两个函数返回?
    wu1990
        17
    wu1990  
    OP
       2017-06-17 15:36:11 +08:00
    @Immortal 我觉在 controller 里,也可以再加一层负责格式化的,controller 确定需要什么格式,然后将 service 里获取到的数据扔进去格式化
    Immortal
        18
    Immortal  
       2017-06-17 15:36:33 +08:00
    @neoblackcap 大概明白了.那这么理解的话,controller 里会包含点调用逻辑么
    比如
    `if service.A() {
    do something
    }else sevice.B() {
    do somtthing
    }`
    还是重新定一个 service.C 在里面全部处理掉?
    Immortal
        19
    Immortal  
       2017-06-17 15:37:51 +08:00
    @wu1990 对这些问题我概念一直有点模糊,不知道有没有开源的教科书式的项目可以学习
    neoblackcap
        20
    neoblackcap  
       2017-06-17 15:47:42 +08:00   ❤️ 1
    @Immortal 在 Controller 里面做就可以了,你想了解更多,看 https://martinfowler.com/,或者买《企业应用架构模式》
    Immortal
        21
    Immortal  
       2017-06-17 17:30:53 +08:00
    @neoblackcap 非常感谢
    hwding
        22
    hwding  
       2017-06-17 18:18:12 +08:00
    我也同意新建一个 service 层,组合简单的数据层语句封装起来,对业务层提供更好的封装。
    wdlth
        23
    wdlth  
       2017-06-17 19:01:04 +08:00
    拿 Symfony 来说,可以写在一个类中,变成 Service,在控制器中使用。
    AlwaysBee
        24
    AlwaysBee  
       2017-06-18 09:51:44 +08:00 via iPhone
    service+1,注入到 controller
    meanmachine
        25
    meanmachine  
       2017-06-18 14:26:52 +08:00 via Android
    可否把简单 sql 逻辑扔 model, 复杂一点的用 repository
    owenliang
        26
    owenliang  
       2017-06-18 16:05:32 +08:00
    再做一个 service 层,把 ORM 调用封装成 API,这样不同的 controller 可以实现复用。

    另外,对 controller 来说,这样只需要组合不同的 service 实现业务,其实也是进一步简化工程复杂度。
    yaxin
        27
    yaxin  
       2017-06-18 21:49:08 +08:00
    如果考虑到之后更改字段或者返回数据处理,还是放 model 处理。我现在就是这样处理的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1007 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 21:59 · PVG 05:59 · LAX 13:59 · JFK 16:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.