当然,由于所有的关联都提供了查询生成器的功能,所以你可以在调用 comments 方法时继续的添加一些限制条件,你可以通过链式的调用进行查询条件的添加:
$comments = App\Post::find(1)->comments()->where('title', 'foo')->first();
就像 hasOne 方法,你可以通过添加额外的参数到 hasMany 方法中来重置外键和主键:
return $this->hasMany('App\Comment', 'foreign_key'); return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
定义相对的关联
现在我们可以访问文章中所有的评论了,让我们为评论定义一个关联使其可以访问它的上层文章模型。为了定义一个 hasMany 相对的关联,你需要在下层模型中定义一个关联方法并调用 belongsTo 方法:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Comment extends Model { /** * Get the post that owns the comment. */ public function post() { return $this->belongsTo('App\Post'); } }
一旦关联被定义完成,我们就可以通过 Comment 模型的 post 动态属性来检索到其对应的 Post 模型:
$comment = App\Comment::find(1); echo $comment->post->title;
在上面的例子中,Eloquent 会尝试从 Comment 模型中的 post_id 字段检索与其相对应 id 的 Post 模型。Eloquent 会使用关联模型的蛇形命名和 _id 来作为默认的外键。如果 Comment 模型的外键不是 post_id,你可以传递一个自定义的键名到 belongsTo 方法的第二个参数:
/** * Get the post that owns the comment. */ public function post() { return $this->belongsTo('App\Post', 'foreign_key'); }
如果上层模型并没有使用 id 作为主键,或者你想在下层模型中关联其他的列,你可以传递第三个参数到 belongsTo 方法中:
/** * Get the post that owns the comment. */ public function post() { return $this->belongsTo('App\Post', 'foreign_key', 'other_key'); }
多对多
多对多的关联比 hasOne 和 hasMany 关联要稍微复杂一些。假如一个用户拥有多个角色,而角色又可以被其他的用户所共享。比如,多个用户可以拥有管理员的角色。如果定义这种关联,我们需要定义三个数据库表:users,roles,和 role_user。role_user 表的命名是以相关联的两个模型数据表来依照字母顺序命名,并且表中包含了 user_id 和 role_id 列。
多对多关联需要编写一个方法调用基础 Eloquent 类 belongsToMany 方法。比如,让我们在 User 模型中定义一个 roles 方法:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * The roles that belong to the user. */ public function roles() { return $this->belongsToMany('App\Role'); } }
一旦关联被定义,你可以通过 roles 动态属性来访问用户的角色:
$user = App\User::find(1); foreach ($user->roles as $role) { // }
当然,就像其他类型的关联,你可以调用 roles 方法并且链式调用查询条件:
$roles = App\User::find(1)->roles()->orderBy('name')->get();
就如先前所提到的,Eloquent 会合并两个关联模型并依照字母顺序进行命名。当然你也可以随意的重写这个约定,你可以传递第二个参数到 belongsToMany 方法:
return $this->belongsToMany('App\Role', 'role_user');
除了自定义合并数据表的名称之外,你也可以通过往 belongsToMany 方法传传递额外参数来自定义数据表里的键的字段名称。第三个参数是你定义在关联中模型外键的名称。第四个参数则是你要合并的模型外键的名称:
return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');
定义相对关联
你只需要在相对应的关联模型里放置其他的方法来调用 belongsToMany 方法就可以定义相对关联。继续我们上面的用户角色示例,让我们在 Role 模型中定义一个 users 方法:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Role extends Model { /** * The users that belongs to the role. */ public function users() { return $this->belongsToMany('App\User'); } }
就如你所看到的,这个关联的定义与用户的关联定义完全相同。因为我们重复的使用了 belongsToMany 方法,当定义相对于多对多的关联时,所有常用的自定义数据表和键的选项都是可用的。
检索中间表字段