1、描述1vs1关系
例如比如又两张表,一张用户表,一张手机表,一个用户只有一个手机,一个手机也只属于一个人,就表达了一对一的关系
class User extends Eloquent {
//一对一
public function phone() {
return $this->hasOne('Phone'); // this matches the Eloquent model
}
class Phone extends Eloquent {
public function user() {
return $this->belongsTo('user'); // this matches the Eloquent model
}
我们可以总结出,在一对一关系中,主表(也就是没有保存user_id表的那个表),用hasOne表示,另外一个表,保存了user_id的,用belongsTo来表述。换句话说,当我们看到一个表有blongsTo的时候,如果后面没有带参数,也就代表着这个表利用方法名_id来跟前面的表关联.
$account = User::find(10)->phone;
这里最难的地方在于后面的两个 foreign_key 和 local_key 的设置,大家可以就此记住:在 User 类中,无论 hasOne 谁,第二个参数都是 `user_id`,第三个参数一般都是 `id`。由于前面的 `find(10)` 已经锁定了 id = 10,所以这段函数对应的 SQL 为: `select * from phone where user_id=10`。
这段代码除了展示了一对一关系该如何使用之外,还传达了三点信息,也是我对于大家使用 Eloquent 时候的建议:
1. 每一个 Model 中都指定表名
2. has one account 这样的关系写成 `hasOneAccount()` 而不是简单的 `account()`
3. 每次使用模型间关系的时候都写全参数,不要省略
2、描述1vs多关系
例如班级表,学生表,一个班级有很多名学生,一个学生只在一个班级,因此class表跟student表是一对多关系
class Squad extends Eloquent {
//一对多
public function student() {
return $this->hasMany('Student');
}
class Student extends Eloquent {
public function squad() {
return $this->belongsTo('Squad');
}
我们可以总结出,在一对多关系中,主表(也就是没有保存squad_id表的那个表),用hasMany表示,另外一个表,保存了squad_id的,用 belongsTo来表述。
3、描述多对多关系
例如角色表,用户表,一个角色有多个用户,一个用户可以拥有多个角色
Class Role extentds Eloquent{
public function users{
return $this->belongsToMany('App\User','user_roles');
}
}
Class User extentds Eloquent{
//多对多关系我们都用复数
public function roles{
return $this->belongsToMany('App\role','user_role');
//(被关联模型,中间表名,关系模型(本类的外键id)的外键名称,连接到的外键名)
return $this->belongsToMany('App\Role', 'user_roles', 'user_id', 'role_id');
}
}
PS:其实我们并非一定要在我们的模型中写这么多可能另我们自己都费解的东西,只是根据需要我们需要进行某些查询的时候才写,举个简单例子,如果我们只需要查一个角色有多少个用户,而我们发现角色跟用户是多对多关系,我们就可以在Role表中写个User方法。如果我们需要查一个班级的所有学生,我们发现班级跟学生是一对多关系,我们就可以在班级模型中写Student方法,用到hasMany。凡是看到有belongsToMany的该模型跟括号里面的肯定是多对多。
4、传统多态模型
文章有点赞功能,评论也有点赞功能,我们的点赞表就有一个字段用来记录表的类型,id记录了文章或评论的id
posts
id - integer
title - string
body - text
comments
id - integer
post_id - integer
body - text
likes
id - integer
likeable_id - integer
likeable_type - string
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Like extends Model{
/**
* 获取所属的likeable模型
*/
public function likeable()
{
return $this->morphTo();
}
}
class Post extends Model{
/**
* 获取该文章的所有点赞
*/
public function likes()
{
return $this->morphMany('App\Like', 'likeable');
}
}
class Comment extends Model{
/**
* 获取该评论的所有点赞
*/
public function likes()
{
return $this->morphMany('App\Like', 'likeable');
}
}
传统的多态比较好理解,就是在文章或评论里面用一个morphMany方法进行关联。传统的多态关联是基于多个一对多表之间的对应关系。
5、多对多的多态关联
多对多的多态关联就稍微复杂点,利用到了类似于我们说的中间表概念,例如我们的文章跟视频都可能有多个标签,于是我们就有了标签表跟标签关联表。
posts
id - integer
name - string
videos
id - integer
name - string
tags
id - integer
name - string
taggables
tag_id - integer
taggable_id - integer
taggable_type - string
关联主体表用morphTomany:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model{
/**
* 获取指定文章所有标签
*/
public function tags()
{
return $this->morphToMany('App\Tag', 'taggable');
}
}
被关联也就是多态模型表用morphedByMany。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model{
/**
* 获取所有分配该标签的文章
*/
public function posts()
{
return $this->morphedByMany('App\Post', 'taggable');
}
/**
* 获取分配该标签的所有视频
*/
public function videos()
{
return $this->morphedByMany('App\Video', 'taggable');
}
}
这是一个主体通过某个中间表在另外一个表中多态的例子,还有一种
通知表notifies,通知发送对象notify_pivots表(一条通知可能发送给一个人,也可能是一个班级,也可能是一个学校),因此这就形成了notifies表通过users表,school表,squards表跟notify_pivots表关联。
notify模型
public function schools() {
return $this->morphedByMany('App\Models\School','notify_pivots');
}
//
public function squads() {
return $this->morphedByMany('App\Models\Squad','notify_pivots');
}
// 这个是消息的接收者是学生或者老师或者其它的方法
public function users() {
return $this->morphedByMany('App\Models\User','notify_pivots');
}