什么是表关联关系
一个数据库中表和表之间必然会存在一些联系,关联关系就是这个意思。
而通过Eloquent我们可以方便的处理这些关系。
定义关联关系
一对一
比如说一个用户(User)会有一个手机(Phone),这种一对一的关系我们直接在User中定义一个phone方法就是可以了。
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model{
/**
* 获取关联到用户的手机
*/
public function phone()
{
return $this->hasOne('App\Phone');
//在这个例子中Phone模型默认有一个user_id外键,
//如果你希望重写这种约定,可以传递第二个参数到hasOne方法。
return $this->hasOne('App\Phone', 'foreign_key');
/*Eloquent 假设外键应该在父级上有一个与之匹配的id,换句话说,Eloquent 将会通过user表的id值去phone表中查询user_id与之匹配的Phone记录。如果你想要关联关系使用其他值而不是id,可以传递第三个参数到hasOne来指定自定义的主键:*/
return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
//说白了就是hasOne('关联Eloquent', '被关联表的key', '本表key')
}
}
使用时
//获取phone实例化
$phone = User::find(1)->phone;
相对应关联
user现在可以找到phone,那么我们怎么通过phone找到user
以此类推实例
namespace App;
use Illuminate\Database\Eloquent\Model;
class Phone extends Model{
/**
* 获取手机对应的用户
*/
public function user()
{
/*Eloquent 将会尝试通过Phone模型的user_id去User模型查找与之匹配的记录。Eloquent 通过关联关系方法名并在方法名后加_id后缀来生成默认的外键名。*/
return $this->belongsTo('App\User');
//参数类似上面的一对一
}
}
一对多
一个文章可以有多条点评
通过文章查找点评 demo
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model{
/**
* 获取文章的点评
* return $this->hasManay('App\Comment(这里是要关联的模型,这个例子是评论模型Comment)', 'article_id'(这里是关联外键的字段名,这个例子就是 article_id 字段), 'id'(对应关联模型的主键,这里的 id 是关联 article 表的id));
}
*/
public function comments()
{
//类似hasOne存在如下参数
return $this->hasMany('App\Comment', 'article_id', 'id ');
}
}
一对多(逆向)
通过点评访问文章。belongsTo
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model{
/**
* 获取点评对应的文章
*/
public function post()
{
return $this->belongsTo('App\Post', 'id', 'article_id');
}
}
多对多
一个用户有多个角色,同时一个角色被多个用户共用。例如,很多用户可能都有一个“Admin”角色。要定义这样的关联关系,需要三个数据表:users、roles和role_user,role_us
er表按照关联模型名的字母顺序命名,并且包含user_id和role_id两个列。
belongsToMany
就是两个表的数据是多对多的关系。
a表的一个数据在b表可以查到多条数据,b表的数据也可以在a表查到多条数据。
当然两个表的关系是通过一个中间表来组织起来的。
中间表的默认命名方式为:a_b,可以修改
多对多的逆向关联和正向是一样的。
用上面的例子:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model{
/**
* 用户角色
*/
public function roles()
{
//可以看到第一个是关联的表,中间表,键,键
return $this->belongsToMany('App\Role', 'user_roles', 'user_id', 'role_id');
}
}
对于Role也一样
namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model{
/**
* 角色用户
*/
public function users()
{
return $this->belongsToMany('App\User');
}
}
关于中间表
上面提到了中间表,这里进行一下扩展:
访问中间表的数据,可以使用pivot属性,他会获得一个中间表的实例。
$user = App\User::find(1);
foreach ($user->roles as $role) {
echo $role->pivot->created_at;
}
当然,在默认情况下通过pivot我们只能访问关联键也就是上例的user_id和role_id。
要想访问其他列,例如上面的created_at需要在关联的时候定义。
使如下方法定义:
//获得column1,column2
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
//获得created_at和updated_at
return $this->belongsToMany('App\Role')->withTimestamps();
关联的时候可以使用wherePivot和wherePivotIn方法过滤结果集。
//要求中间表记录符合approved=1。
return $this->belongsToMany('App\Role')->wherePivot('approved', 1);
//要求中间表记录符合priority在1,2之中。
return $this->belongsToMany('App\Role')->wherePivotIn('priority', [1, 2]);