Eloquent: 关联模型
简介
数据库中的表经常性的关联其它的表。比如,一个博客文章可以有很多的评论,或者一个订单会关联一个用户。Eloquent 使管理和协作这些关系变的非常的容易,并且支持多种不同类型的关联:
一对一
一对多
多对多
远程一对多
多态关联
多态多对多关联
定义关联
Eloquent 关联可以像定义方法一样在 Eloquent 模型类中进行定义。同时,它就像 Eloquent 模型自身一样也提供了强大的查询生成器。这允许关联模型可以链式的执行查询能力。比如:
posts()->where('active',1)->get();
但是,在更深入的使用关联之前,让我们先来学习一下如何定义各种类型的关联。
一对一
一对一的关联是最基础的关联。比如,一个 User 模型可能关联一个 Phone。我们需要在 User 模型上放置一个 phone 方法来定义这种关联。phone 方法应该返回一个基类 Eloquent 模型上 hasOne 方法的结果:
namespace App;
use IlluminateDatabaseEloquentModel;
class User extends Model
{
/**
- Get the phone record associated with the user.
*/
public function phone()
{
return $this->hasOne('AppPhone');
}
}
传递到 hasOne 方法的第一个参数应该是关联模型的名称。一旦关联被定义完成,我们可以使用 Eloquent 的动态属性来访问关联模型的记录。动态属性允许你访问关联函数,就像是它们是定义在模型中的属性一样:
phone;
Eloquent 假定所关联的外键是基于模型的名称的。在这个前提下,Phone 模型会自动的假定其拥有一个 user_id 外键。如果你希望修改这个惯例,你可以传递第二个参数到 hasOne 方法中:
hasOne('AppPhone','foreign_key');
另外,Eloquent 也会假定外键应该在其上层模型上拥有一个匹配的 id(或者自定义的 $primaryKey)值。换句话说,Eloquent 会查询 Phone 记录中的 user_id 列所对应的用户的 id 列的记录。如果你希望关联使用 id 以外的值,你可以传递第三个参数到 hasOne 方法来指定自定义的键:
hasOne('AppPhone','foreign_key','local_key');
定义相对的关联
那么,我们可以从我们的 User 中访问 Phone 模型。现在,让我们在 Phone 模型上定义一个关联,让我们可以从 Phone 模型中访问其所属的 User。我们使用 belongsTo 方法来定义 hasOne 相对的关联:
namespace App;
use IlluminateDatabaseEloquentModel;
class Phone extends Model
{
/**
- Get the user that owns the phone.
*/
public function user()
{
return $this->belongsTo('AppUser');
}
}
在上面的例子中,Eloquent 将会尝试从 Phone 模型中的 user_id 字段中匹配查找 id 相同的 User。Eloquent 会依据所关联的模型的蛇形命名和 _id 来假定默认的外键名。事实上,如果在 Phone 模型上的外键不是 user_id,那么你可以传递自定义的外键名到 belongsTo 方法的第二个参数:
- Get the user that owns the phone.
*/
public function user()
{
return $this->belongsTo('AppUser','foreign_key');
}
如果你的上级模型并没有使用 id 作为主键名,或者你希望下级模型关联一个不同的列。你可以传递第三个参数到 belongsTo 方法来指定上级模型表中的自定义键:
- Get the user that owns the phone.
*/
public function user()
{
return $this->belongsTo('AppUser','other_key');
}
一对多
一个一对多的关联常常用来定义一个模型拥有其他任意数目的模型。比如,一个博客文章可以拥有很多条评论。就像其他的 Eloquent 关联一样,一对多关联在 Eloquent 模型中通过方法来进行定义:
namespace App;
use IlluminateDatabaseEloquentModel;
class Post extends Model
{
/**
- Get the comments for the blog post.
*/
public function comments()
{
return $this->hasMany('AppComment');
}
}
记住,Eloquent 会自动的根据 Comment 模型来判断合适的外键。依据惯例,Eloquent 会使用自身模型的蛇形命名和 _id 来作为外键。所以,在这个例子中,Eloquent 会假定 Comment 模型的外键是 post_id。
一旦关联定义完成之后,我们可以通过 comments 属性来访问所有关联的评论的集合。记住,由于 Eloquent 提供了动态属性,我们可以对关联函数进行访问,就像他们是在模型中定义的属性一样:
comments;
foreach ($comments as $comment) {
//
}
当然,由于所有的关联都提供了查询生成器的功能,所以你可以在调用 comments 方法时继续的添加一些限制条件,你可以通过链式的调用进行查询条件的添加:
comments()->where('title','foo')->first();
就像 hasOne 方法,你可以通过添加额外的参数到 hasMany 方法中来重置外键和主键:
hasMany('AppComment','foreign_key');
return $this->hasMany('AppComment','local_key');
定义相对的关联
现在我们可以访问文章中所有的评论了,让我们为评论定义一个关联使其可以访问它的上层文章模型。为了定义一个 hasMany 相对的关联,你需要在下层模型中定义一个关联方法并调用 belongsTo 方法:
namespace App;
use IlluminateDatabaseEloquentModel;
class Comment extends Model
{
/**
echo $comment->post->title;
在上面的例子中,Eloquent 会尝试从 Comment 模型中的 post_id 字段检索与其相对应 id 的 Post 模型。Eloquent 会使用关联模型的蛇形命名和 _id 来作为默认的外键。如果 Comment 模型的外键不是 post_id,你可以传递一个自定义的键名到 belongsTo 方法的第二个参数:
belongsTo('AppPost','foreign_key');
}
如果上层模型并没有使用 id 作为主键,或者你想在下层模型中关联其他的列,你可以传递第三个参数到 belongsTo 方法中:
belongsTo('AppPost','other_key');
}
多对多
多对多的关联比 hasOne 和 hasMany 关联要稍微复杂一些。假如一个用户拥有多个角色,而角色又可以被其他的用户所共享。比如,多个用户可以拥有管理员的角色。如果定义这种关联,我们需要定义三个数据库表:users,roles,和 role_user。role_user 表的命名是以相关联的两个模型数据表来依照字母顺序命名,并且表中包含了 user_id 和 role_id 列。
多对多关联需要编写一个方法调用基础 Eloquent 类 belongsToMany 方法。比如,让我们在 User 模型中定义一个 roles 方法:
namespace App;
use IlluminateDatabaseEloquentModel;
class User extends Model
{
/**
foreach ($user->roles as $role) {
//
}
当然,就像其他类型的关联,你可以调用 roles 方法并且链式调用查询条件:
roles()->orderBy('name')->get();
就如先前所提到的,Eloquent 会合并两个关联模型并依照字母顺序进行命名。当然你也可以随意的重写这个约定,你可以传递第二个参数到 belongsToMany 方法:
belongsToMany('AppRole','role_user');
除了自定义合并数据表的名称之外,你也可以通过往 belongsToMany 方法传传递额外参数来自定义数据表里的键的字段名称。第三个参数是你定义在关联中模型外键的名称。第四个参数则是你要合并的模型外键的名称:
belongsToMany('AppRole','role_user','user_id','role_id');
定义相对关联
(编辑:安卓应用网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|