使用 Laravel ORM 时的一个问题?

2016-08-12 08:45:13 +08:00
 chenset

我们团队使用 ORM 写了两个例子, 争论这两个例子的优缺点. 麻烦帮忙分析一下.

问题: 需要取得用户的所有车辆, 这个方法应该写在 User 中还是 Car 中.

表结构: user: [ id, ]

car: [ id, user_id, car_status, ]

Laravel ORM 代码:

<?php
class User extends \Illuminate\Database\Eloquent\Model
{
    // 例子 1: 将取用户所有车辆的方法写在 User 中, user ID 参数使用$this->id
    // 例子 1 的理由是: 因为要取得用户的所属车辆, 出发点是 User 对象所以方法应该写在 User 中, 这样会更加面向对象.
    public function myCars()
    {
        return Car::where(['user_id' => $this->id, 'car_status' => 1])->get();
    }
}

class Car extends \Illuminate\Database\Eloquent\Model
{
    // 例子 2: 将取用户所有车辆的方法写在 Car 中, user ID 参数使用通过方法传递进来
    // 例子 2 的理由是: 因为所查询的是 Car 表, user ID 应该作为 Car 的一个属性传递给 Car.list 方法,而且$moreCondition 可以日后增加更多筛选条件复用性好.
    public function list(int $userID, $moreCondition...)
    {
        return $this->where(['user_id' => $userID, $moreCondition...])->get();
    }
}

不使用关联关系不手写 SQL 时, 我们团队在争论这两种写法的优劣, 想看看大家的看法.

例子 1: 将取用户所有车辆的方法写在 User 中, user ID 参数使用$this->id 例子 1 的理由是: 因为要取得用户的所属车辆, 出发点是 User 对象所以方法应该写在 User 中, 这样会更加面向对象.

例子 2: 将取用户所有车辆的方法写在 Car 中, user ID 参数使用通过方法传递进来 例子 2 的理由是: 因为所查询的是 Car 表, user ID 应该作为 Car 的一个属性传递给 Car.list 方法,而且$moreCondition 可以日后增加更多筛选条件复用性好.

主要想问的是这个方法应该写在 User 中还是 Car 中.

6245 次点击
所在节点    PHP
45 条回复
caola
2016-08-13 01:22:55 +08:00
表的名称应该为复数,多数情况下是加上个“ s ”, user 表名应该为 users ,这也是 laravel 默认的命名方式。
ORM 中如果不是这样复数的表,你可能要多写几个代码

-----抱歉,我并没有回答你的问题-----
miaotaizi
2016-08-13 11:33:01 +08:00
@MrJing1992
如果是我我就把这个方法写在 car 中,并且为一个静态方法.
首先你取得的是 car ,而不是 user ,这一点就应该在 car 中
.
并且你这个方法想必跟 car 实体本身没什么太大关系,那这个方法就应该是一个静态方法.
至于如何在 user 获取所有的 car ,那就是 user 如何去调用 car 类中的方法的事儿了.
kzzhr
2016-08-14 09:04:11 +08:00
@assad 用 relation 在将来可以写 whereHas (a.b.c.d ),手写 SQL 不会疯?
assad
2016-08-14 11:46:59 +08:00
@kzzhr 我们的 SQL 都是一个连很多张表的,动不动就半页 SQL ,自然不能 ORM 了
AbrahamGreyson
2016-08-18 00:51:10 +08:00
个人觉得这和 ORM 与否没什么关系,不是 Eloquent 才会出现的疑惑,更和面向对象没关系,因为我们的开发,早已经假设一切问题都建立在 oop 之上。并不是说 this.id 就是 oop , oop 更多的是一种思考问题的方式。

我们从思考问题的方式出发。

首先还得看业务需求,如果 User 是一个模块 /领域模型 /聚集的根(主入口,唯一标识),那么它内部所维护的各个值对象理应通过 User 来拿,我们姑且以模块来称呼这个 User 的功能,如果 User 这个模块的一个重要功能是按照特定的 User 实体去获得属于他的 /关联的其它对象,我想不出为什么不直接写在 User 数据库类中,因为,特定的用户不存在的时候,与他相关的一切其它值都将失去意义。 Laravel ORM 把对象关系映射、实体、模块聚集浓缩到了一层中,直接去在 User 对象中访问模块内部的其它元素便是了。然后你可能因为测试 /关注分离 /业务和基础设施分离等原因,可能会在客户端代码和 User 对象中增加类似 Repository 、 Factory 之类的东西,这个时候 Factory 返回的将是一个 User 模块的聚集,它的根是 User 对象,它的其它元素,就是你自己维护的与 User 对象相关的其它实体。

尽管这样我也见过有人用另一种方式,也就是使用动态的数据库查询去返回对象(楼主的方法 2 ),这么做的目的是给 User 模块瘦身,但是我个人偏好第一种。第一种方式拿 User 的关联元素, 维护时可能仅仅需要修改特定类的方法,第二种则要修改分散到系统各处的条件,甚至更复杂些,有人用对象表示查询条件。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/298782

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX