使用 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 中.

6038 次点击
所在节点    PHP
45 条回复
sujin190
2016-08-12 09:43:53 +08:00
@chenset 看你描述的这个场景我觉得还是第二种比较好
laoyuan
2016-08-12 09:52:39 +08:00
你们团队都没有看过文档的 Tutorials 么
https://laravel.com/docs/5.2/quickstart-intermediate#eloquent-relationships

class User extends Authenticatable
{
// Other Eloquent Properties...

/**
* Get all of the tasks for the user.
*/
public function tasks()
{
return $this->hasMany(Task::class);
}
laoyuan
2016-08-12 09:53:55 +08:00
20%的回复提到了 hasMany(),靠谱!
aggron
2016-08-12 10:02:48 +08:00
赞同 @sujin190 我觉得还是放在 Car 中合适些,系统里与 User 相关的 model 太多了,放里面只会越来越庞大,个人觉得为了“更面向对象”放里面不是个好的设计
随便选一个算是智者见智吧,可以参考下领域模型中的相关设计 http://www.oschina.net/question/98375_21638
MrJing1992
2016-08-12 10:09:15 +08:00
按业务逻辑拆分功能。
当你上 Car 这个业务时,就有了“用户所有的车”这个功能。当你要下线 Car 这个业务时,如果你还有去改 User 业务的代码那是不太合理的。
所有结论就是:这个功能属于 Car 业务,就放在 Car 业务相关的代码里面。
jinchun
2016-08-12 10:55:27 +08:00
model 里应该都是 hasMany 和 belongsTO 的关系。。你这代码应该是放在 repositories 里。具体看这个:
http://slashnode.com/reusable-repository-design-in-laravel/
lzsadam
2016-08-12 11:10:15 +08:00
多表查询的话我是以主表为主的
这里的主表应该是 car
话说我也会写在 service 层
chenset
2016-08-12 11:23:28 +08:00
@laoyuan 你都没有看帖子吗? "不使用关联关系不手写 SQL 时, 我们团队在争论这两种写法的优劣, 想看看大家的看法."
SayHaHa
2016-08-12 11:28:33 +08:00
支持写在 User 中
Liang
2016-08-12 11:43:52 +08:00
要看是否一辆车是否属于多个人,或一个人是否拥有多辆车。
看数据表结构,应该是后者。

我习惯会把"->"当成"的"。$user->cars()会更好, User 中使用 hasMany()。

个人习惯~不代表权威
mahone3297
2016-08-12 11:49:00 +08:00
写在 User 中?那一个用户,如果有多辆车,那是 User 表中多条数据?那还叫 User 表? User 表不是一个 user 一条数据?
shuson
2016-08-12 11:50:47 +08:00
hasMany 是正解,不要 anti pattern
wanghanlin
2016-08-12 12:00:11 +08:00
还是推荐使用 relationships ,没必要这么搞,不过回到这个问题,还是放 User 里合适
assad
2016-08-12 13:47:42 +08:00
一个破 SQL ,费用要什么 HasMany ,遇到复杂设计的,奇葩需求的,统统不好使。真心不喜欢框架这种 ORM ,简单的业务还行,一遇到复杂的需求,还是直接写 SQL ,建立一个 model ,自己处理的好!
justfindu
2016-08-12 13:51:38 +08:00
按你这个设计 那就应该放第二种, 并且 user_id 不作为必要条件 这样更能复用
silov
2016-08-12 13:53:09 +08:00
hasMany 和 belongsTo 什么的可以很好的完成你的需求,尤其是配合预加载的时候。

顺便吐槽一下第一种,你在一个 Model 里面写另一个 model 的 where 条件查询,不觉得怪么?
zhangchaozheng
2016-08-12 16:28:10 +08:00
孩纸们,忘掉 ORM 这种东西吧!
pein
2016-08-12 16:58:29 +08:00
@inmyfree 哈,你这把 android 黑得毫无破绽啊,高!
cxbig
2016-08-12 17:59:15 +08:00
1. 肯定会定义关联
2. User->myCars()
klgd
2016-08-12 22:45:20 +08:00
如果在不使用关联关系的情况下,我选第二种,各自操作各自的表,互不干扰
当然要是用关联关系的话,那就是 User 里使用 hasMany

ps :我觉得比较规范点儿的表结构是 users , cars , user_car 三个表

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

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

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

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

© 2021 V2EX