Eloquent: 关联模型
简介
数据库中的表经常性的关联其它的表。比如,一个博客文章可以有很多的评论,或者一个订单会关联一个用户。Eloquent 使管理和协作这些关系变的非常的容易,并且支持多种不同类型的关联:
一对一
一对多
多对多
远程一对多
多态关联
多态多对多关联
定义关联
Eloquent 关联可以像定义方法一样在 Eloquent 模型类中进行定义。同时,它就像 Eloquent 模型自身一样也提供了强大的查询生成器。这允许关联模型可以链式的执行查询能力。比如:
$user->posts()->where('active', 1)->get();
但是,在更深入的使用关联之前,让我们先来学习一下如何定义各种类型的关联。
一对一
一对一的关联是最基础的关联。比如,一个 User 模型可能关联一个 Phone。我们需要在 User 模型上放置一个 phone 方法来定义这种关联。phone 方法应该返回一个基类 Eloquent 模型上 hasOne 方法的结果:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * Get the phone record associated with the user. */ public function phone() { return $this->hasOne('App\Phone'); } }
传递到 hasOne 方法的第一个参数应该是关联模型的名称。一旦关联被定义完成,我们可以使用 Eloquent 的动态属性来访问关联模型的记录。动态属性允许你访问关联函数,就像是它们是定义在模型中的属性一样:
$phone = User::find(1)->phone;
Eloquent 假定所关联的外键是基于模型的名称的。在这个前提下,Phone 模型会自动的假定其拥有一个 user_id 外键。如果你希望修改这个惯例,你可以传递第二个参数到 hasOne 方法中:
return $this->hasOne('App\Phone', 'foreign_key');
另外,Eloquent 也会假定外键应该在其上层模型上拥有一个匹配的 id(或者自定义的 $primaryKey)值。换句话说,Eloquent 会查询 Phone 记录中的 user_id 列所对应的用户的 id 列的记录。如果你希望关联使用 id 以外的值,你可以传递第三个参数到 hasOne 方法来指定自定义的键:
return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
定义相对的关联
那么,我们可以从我们的 User 中访问 Phone 模型。现在,让我们在 Phone 模型上定义一个关联,让我们可以从 Phone 模型中访问其所属的 User。我们使用 belongsTo 方法来定义 hasOne 相对的关联:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Phone extends Model { /** * Get the user that owns the phone. */ public function user() { return $this->belongsTo('App\User'); } }
在上面的例子中,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('App\User', 'foreign_key'); }
如果你的上级模型并没有使用 id 作为主键名,或者你希望下级模型关联一个不同的列。你可以传递第三个参数到 belongsTo 方法来指定上级模型表中的自定义键:
/** * Get the user that owns the phone. */ public function user() { return $this->belongsTo('App\User', 'foreign_key', 'other_key'); }
一对多
一个一对多的关联常常用来定义一个模型拥有其他任意数目的模型。比如,一个博客文章可以拥有很多条评论。就像其他的 Eloquent 关联一样,一对多关联在 Eloquent 模型中通过方法来进行定义:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model { /** * Get the comments for the blog post. */ public function comments() { return $this->hasMany('App\Comment'); } }
记住,Eloquent 会自动的根据 Comment 模型来判断合适的外键。依据惯例,Eloquent 会使用自身模型的蛇形命名和 _id 来作为外键。所以,在这个例子中,Eloquent 会假定 Comment 模型的外键是 post_id。
一旦关联定义完成之后,我们可以通过 comments 属性来访问所有关联的评论的集合。记住,由于 Eloquent 提供了动态属性,我们可以对关联函数进行访问,就像他们是在模型中定义的属性一样:
$comments = App\Post::find(1)->comments; foreach ($comments as $comment) { // }