深入理解 Laravel Eloquent(三)——模型间关系(关联)
原文发表在我的个人网站:深入理解 Laravel Eloquent(三)——模型间关系(关联)
在本篇文章中,我将跟大家一起学习 Eloquent 中最复杂也是最难理解的部分——模型间关系。官方英文文档中叫 Relationships,个人认为翻译成 “模型间关系” 比现在的 “关联” 更好理解一点哈哈。
Eloquent是什么
Eloquent 是一个 ORM,全称为 Object Relational Mapping,翻译为 “对象关系映射”(如果只把它当成 Database Abstraction Layer 数组库抽象层那就太小看它了)。所谓 “对象”,就是本文所说的 “模型(Model)”;对象关系映射,即为模型间关系。中文文档: http://laravel-china.org/docs/eloquent#relationships
下面我们开始一个一个地学习。
一对一关系
顾名思义,这描述的是两个模型之间一对一的关系。这种关系是不需要中间表的。
假如我们有两个模型:User 和 Account,分别对应注册用户和消费者,他们是一对一的关系,那么如果我们要使用 Eloquent 提供的一对一关系方法,表结构应该是这样的:
ruby
user: id ... ... account_id account: id ... ... user_id
假设我们需要在 User 模型中查询对应的 Account 表的信息,那么代码应该是这样的。
/app/models/User.php:
php
<?php class User extends Eloquent { protected $table = 'users'; public function hasOneAccount() { return $this->hasOne('Account', 'user_id', 'id'); } }
然后,当我们需要用到这种关系的时候,该如何使用呢?如下:
php
$account = User::find(10)->hasOneAccount;
此时得到的
$account即为
Account类的一个实例。
这里最难的地方在于后面的两个 foreign_key 和 local_key 的设置,大家可以就此记住:在 User 类中,无论 hasOne 谁,第二个参数都是
user_id,第三个参数一般都是
id。由于前面的
find(10)已经锁定了 id = 10,所以这段函数对应的 SQL 为:
select * from account where user_id=10。
这段代码除了展示了一对一关系该如何使用之外,还传达了三点信息,也是我对于大家使用 Eloquent 时候的建议:
- 每一个 Model 中都指定表名
- has one account 这样的关系写成
hasOneAccount()而不是简单的account()- 每次使用模型间关系的时候都写全参数,不要省略
相应的,如果使用 belongsTo() 关系,应该这么写:
php
<?php class Account extends Eloquent { protected $table = 'accounts'; public function belongsToUser() { return $this->belongsTo('User', 'user_id', 'id'); } }
一对多关系
学会了前面使用一对一关系的基础方法,后面的几种关系就简单多了。
我们引入一个新的Model:Pay,付款记录。表结构应该是这样的:
ruby
user: id ... ... pay: id ... ... user_id
User 和 Pay 具有一对多关系,换句话说就是一个 User 可以有多个 Pay,这样的话,只在 Pay 表中存在一个
user_id字段即可。
/app/models/User.php:
php
<?php class User extends Eloquent { protected $table = 'users'; public function hasManyPays() { return $this->hasMany('Pay', 'user_id', 'id'); } }
然后,当我们需要用到这种关系的时候,该如何使用呢?如下:
php
$accounts = User::find(10)->hasManyPays()->get();
此时得到的
$accounts即为
Illuminate\Database\Eloquent\Collection类的一个实例。大家应该也已经注意到了,这里不是简单的
-> hasOneAccount而是
->hasManyPays()->get(),为什么呢?因为这里是
hasMany,操作的是一个对象集合。
相应的 belongsTo() 的用法跟上面一对一关系一样:
php
<?php class Pay extends Eloquent { protected $table = 'pays'; public function belongsToUser() { return $this->belongsTo('User', 'user_id', 'id'); } }
多对多关系
多对多关系和之前的关系完全不一样,因为多对多关系可能出现很多冗余数据,用之前自带的表存不下了。
我们定义两个模型:Article 和 Tag,分别表示文章和标签,他们是多对多的关系。表结构应该是这样的:
ruby
article: id ... ... tag: id ... ... article_tag: article_id tag_id
在 Model 中使用:
php
<?php class Tag extends Eloquent { protected $table = 'tags'; public function belongsToManyArticle() { return $this->belongsToMany('Article', 'article_tag', 'tag_id', 'article_id'); } }
需要注意的是,第三个参数是本类的 id,第四个参数是第一个参数那个类的 id。
使用跟 hasMany 一样:
php
$tagsWithArticles = Tag::take(10)->get()->belongsToManyArticle()->get();
这里会得到一个非常复杂的对象,可以自行
var_dump()。跟大家说一个诀窍,
var_dump()以后,用 Chrome 右键 “查看源代码”,就可以看到非常整齐的对象/数组展开了。
在这里给大家展示一个少见用法(奇技淫巧):
phppublic function parent_video() { return $this->belongsToMany($this, 'video_hierarchy', 'video_id', 'video_parent_id'); } public function children_video() { return $this->belongsToMany($this, 'video_hierarchy', 'video_parent_id', 'video_id'); }对,你没有看错,可以 belongsToMany 自己。
其他关系
Eloquent 还提供 “远层一对多关联”、“多态关联” 和 “多态的多对多关联” 这另外三种用法,经过上面的学习,我们已经掌握了 Eloquent 模型间关系的基本概念和使用方法,剩下的几种不常用的方法就留到我们用到的时候再自己探索吧。
重要技巧:关系预载入
你也许已经发现了,在一对一关系中,如果我们需要一次性查询出10个 User 并带上对应的 Account 的话,那么就需要给数据库打 1 + 10 条 SQL,这样性能是很差的。我们可以使用一个重要的特性,关系预载入:http://laravel-china.org/docs/eloquent#eager-loading
直接上代码:
php
$users = User::with('hasOneAccount')->take(10)->get()
这样生成的 SQL 就是这个样子的:
sql
select * from account where id in (1, 2, 3, ... ...)
这样 1 + 10 条 SQL 就变成了 1 + 1 条,性能大增。
至此,深入理解 Laravel Eloquent 系列文章到此结束。推荐继续了解 软删除 、转换成数组/JSON。
END
- 深入理解 Laravel Eloquent(三)——模型间关系(关联)
- 深入理解 Laravel Eloquent(三)——模型间关系(关联)
- 深入理解 Laravel Eloquent(三)——模型间关系(关联)
- 深入理解 Laravel Eloquent(三)——模型间关系(关联)
- 深入理解 Laravel Eloquent(三)——模型间关系(关联) 在本篇文章中,我将跟大家一起学习 Eloquent 中最复杂也是最难理解的部分——模型间关系。官方英文文档中叫 Relatio
- 深入理解 Laravel Eloquent(一)——基本概念及用法
- 深入理解 Laravel Eloquent(二)——中间操作流(Builder)
- [李景山php]每天laravel[035]-laravel 基础知识 --- Eloquent 模型之关系映射
- 深入理解 Laravel Eloquent(一)——基本概念及用法
- laravel 5.5 -- Eloquent 模型关联
- Laravel 5.1 文档攻略 —— Eloquent:模型关系
- 深入理解 Laravel Eloquent(二)——中间操作流(Builder)
- laravel eloquent 模型关联
- 每天laravel[035]-laravel 基础知识 --- Eloquent 模型之关系映射
- 深入理解 Laravel Eloquent(一)——基本概念及用法
- 深入理解JVM(一)——JVM内存模型
- 【原创翻译】深入理解javascript事件处理函数绑定三部曲(三)——高级事件函数绑定模型
- 14. Laravel 4 Eloquent 模型对象关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- 深入理解JVM内存模型