wu1990
V2EX  ›  PHP

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

  •  
  •   wu1990 · Jun 17, 2017 · 4866 views
    This topic created in 3261 days ago, the information mentioned may be changed or developed.

    下面的(伪)代码都基于 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 replies    2017-06-18 21:49:08 +08:00
    mrcn
        1
    mrcn  
       Jun 17, 2017
    我觉得应该在控制器直接调用比较好。

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

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

    另外,对 controller 来说,这样只需要组合不同的 service 实现业务,其实也是进一步简化工程复杂度。
    yaxin
        27
    yaxin  
       Jun 18, 2017
    如果考虑到之后更改字段或者返回数据处理,还是放 model 处理。我现在就是这样处理的。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   4818 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 105ms · UTC 09:45 · PVG 17:45 · LAX 02:45 · JFK 05:45
    ♥ Do have faith in what you're doing.