laravel学习教程之关联模型
Eloquent: 关联模型简介数据库中的表经常性的关联其它的表。比如,一个博客文章可以有很多的评论,或者一个订单会关联一个用户。Eloquent 使管理和协作这些关系变的非常的容易,并且支持多种不同类型的关联: 一对一一对多多对多远程一对多多态关联多态多对多关联定义关联Eloquent 关联可以像定义方法一样在 Eloquent 模型类中进行定义。同时,它就像 Eloquent 模型自身一样也提供了强大的查询生成器。这允许关联模型可以链式的执行查询能力。比如: posts()->where('active',1)->get();
但是,在更深入的使用关联之前,让我们先来学习一下如何定义各种类型的关联。 一对一一对一的关联是最基础的关联。比如,一个 namespace App;
use IlluminateDatabaseEloquentModel; class User extends Model
传递到 phone;
Eloquent 假定所关联的外键是基于模型的名称的。在这个前提下, hasOne('AppPhone','foreign_key');
另外,Eloquent 也会假定外键应该在其上层模型上拥有一个匹配的 hasOne('AppPhone','foreign_key','local_key');
定义相对的关联那么,我们可以从我们的 namespace App; use IlluminateDatabaseEloquentModel; class Phone extends Model
在上面的例子中,Eloquent 将会尝试从 */ public function user() { return $this->belongsTo('AppUser','foreign_key'); } 如果你的上级模型并没有使用 */ public function user() { return $this->belongsTo('AppUser','other_key'); } 一对多一个一对多的关联常常用来定义一个模型拥有其他任意数目的模型。比如,一个博客文章可以拥有很多条评论。就像其他的 Eloquent 关联一样,一对多关联在 Eloquent 模型中通过方法来进行定义: namespace App; use IlluminateDatabaseEloquentModel; class Post extends Model
记住,Eloquent 会自动的根据 一旦关联定义完成之后,我们可以通过 comments;
foreach ($comments as $comment) { 当然,由于所有的关联都提供了查询生成器的功能,所以你可以在调用 comments()->where('title','foo')->first();
就像 hasMany('AppComment','foreign_key');
return $this->hasMany('AppComment','local_key'); 定义相对的关联现在我们可以访问文章中所有的评论了,让我们为评论定义一个关联使其可以访问它的上层文章模型。为了定义一个 namespace App;
use IlluminateDatabaseEloquentModel; class Comment extends Model
一旦关联被定义完成,我们就可以通过 echo $comment->post->title; 在上面的例子中, belongsTo('AppPost','foreign_key');
}
如果上层模型并没有使用 id 作为主键,或者你想在下层模型中关联其他的列,你可以传递第三个参数到 belongsTo 方法中: belongsTo('AppPost','other_key');
}
多对多多对多的关联比 多对多关联需要编写一个方法调用基础 namespace App;
use IlluminateDatabaseEloquentModel; class User extends Model
一旦关联被定义,你可以通过 foreach ($user->roles as $role) { 当然,就像其他类型的关联,你可以调用 roles()->orderBy('name')->get();
就如先前所提到的,Eloquent 会合并两个关联模型并依照字母顺序进行命名。当然你也可以随意的重写这个约定,你可以传递第二个参数到 belongsToMany('AppRole','role_user');
除了自定义合并数据表的名称之外,你也可以通过往 belongsToMany('AppRole','role_user','user_id','role_id');
定义相对关联你只需要在相对应的关联模型里放置其他的方法来调用 namespace App;
use IlluminateDatabaseEloquentModel; class Role extends Model
就如你所看到的,这个关联的定义与用户的关联定义完全相同。因为我们重复的使用了 检索中间表字段正如你已经了解到的。定义多对多的关联需要引入一个中间表。Eloquent 提供了几种非常有帮助的方式来与这个表进行交互。比如,让我们假定我们的 foreach ($user->roles as $role) { 注意我们取出的每个 默认的,只有模型的键会被 belongsToMany('AppRole')->withPivot('column1','column2');
如果你想要中间表自动维护 belongsToMany('AppRole')->withTimestamps();
通过中间表字段过滤关系你可以通过在定义关联时使用 belongsToMany('AppRole')->wherePivot('approved',1);
return $this->belongsToMany('AppRole')->wherePivotIn('approved',[1,2]); 远程一对多远程一对多关联提供了简短便捷的方法通过中间关联件来访问远端的关联。比如,一个 users
id - integer country_id - integer name - string posts 远端的 现在我们已经明确了关联表的结构,那么让我们来在 Country 模型上定义关联: namespace App;
use IlluminateDatabaseEloquentModel; class Country extends Model
传递到 当使用关联查询时,通常 Eloquent 会遵循外键约定。如果你希望对关联的键进行自定义,你可以传递第三和第四个参数到 hasManyThrough(
'AppPost','AppUser','country_id','id'
);
}
}
多态关联表结构多态关联允许一个模型在单个关联中从属一个或多个其它模型。比如,想象一下应用中的用户可以喜欢文章及其评论。如果使用多态关联,那么你就可以使用一个单独的 comments likes 你需要注意到的两个在 模型结构接着,让我们检查一下这个关联所需要的模型定义: namespace App;
use IlluminateDatabaseEloquentModel; class like extends Model
class Post extends Model
class Comment extends Model
获取多态关联一旦数据库表和模型都定义完成,你就可以在你的模型中访问这些关联。比如,你可以使用 foreach ($post->likes as $like) { 你也可以通过在模型上调用提供 $likeable = $like->likeable;
自定义多态类型默认的,Laravel 会使用包完全限定类名来存储所关联模型的类型。比如,上面的例子中 Relation::morphMap([
AppPost::class,AppComment::class,]); 或者,你可以指定一个自定的字符串与每个模型进行关联: Relation::morphMap([
'posts' => AppPost::class,'likes' => AppLike::class,]); 你可以在你的 多态多对多关联表结构除了传统的多态关联,你也可以定义多对多的多态关联。比如,一个博客的 videos
id - integer name - string tags taggables 模型结构接着,我们来定义模型中的关联。 namespace App;
use IlluminateDatabaseEloquentModel; class Post extends Model
定义相对的关联接着,在 namespace App; use IlluminateDatabaseEloquentModel; class Tag extends Model
/**
获取关联当定义完成数据表和模型之后,你就可以通过模型来访问其关联。比如,你可以简单的使用 foreach ($post->tags as $tag) { 你也可以通过访问模型中提供执行 foreach ($tag->videos as $video) {
// } 关联查询由于所有的 Eloquent 关联类型都是通过方法定义的,所以你可以调用这些方法来获取所关联的模型的实例而无需实际的执行关联查询。另外,所有的 Eloquent 关联也都提供了查询生成器服务,这允许你可以继续的链式执行查询操作。 比如,想象一下博客系统中 namespace App;
use IlluminateDatabaseEloquentModel; class User extends Model
你可以查询 $user->posts()->where('active',1)->get(); 你应该注意到了,你可以在关联中使用任何的查询生成器的方法。 关联方法 Vs. 动态属性如果你不需要在进行 Eloquent 关联查询时添加额外的约束,你可以简单的像它的属性一样进行访问。比如,我们继续使用 foreach ($user->posts as $post) {
// } 动态属性是惰性加载的,这意味着在你实际访问他们之前,其关联数据是不会加载的。正因为如此,开发的时候通常使用预加载来进行加载一些即将用到的关联模型。预加载要求必须加载一个模型的关系,这有效的减少了查询的次数。 查询关联是否存在当访问一个模型的记录时,你可能会希望基于关联的记录是否存在来对结果进行限制。比如,想象一下你希望获取最少有一条评论的博客文章。你可以传递关联的名称到 get();
你也可以指定操作符,和数量来进一步定制查询: =',3)->get();
你也可以使用 . 语法来构造嵌套的 get();
如果你需要更高的控制,你可以使用 where('content','like','foo%');
})->get();
统计关联结果如果你希望统计关联的结果而不实际的加载它们,你可以使用 get();
foreach ($posts as $post) { 你也可以同时检索多个关联的统计,以及添加查询约束: function ($query) {
$query->where('content','foo%');
}])->get();
echo $posts[0]->votes_count; 预加载当通过属性访问 Eloquent 关联时,该关联的数据会被延迟加载。这意味着该关联数据只有在你真实的访问属性时才会进行加载。事实上,Eloquent 可以在上层模型中一次性预加载的。预加载有效避免了 N + 1 的查找问题。要说明 N + 1 查找问题,我们可以来看一个 namespace App;
use IlluminateDatabaseEloquentModel; class Book extends Model
现在,让我们检索所有的书籍和他们的作者: foreach ($books as $book) { 这个循环会执行一次查找回所有的书籍,接着每本书会运行一次查找作者的操作。所以,如果我们拥有 25 本书,那么循环将会进行 26 次查询:1 次查询所有的书籍,25 次查询相关书籍的作者。 非常幸运的,我们可以使用预加载来将查询有效的控制在 2 次。当查询时,使用 get();
foreach ($books as $book) { 对于这个操作,只会执行两个查询: select * from authors where id in (1,2,3,4,5,...)
预加载多个关联有时候你可能需要在一个操作中预加载多个关联,你只需要传递额外的参数到 get();
嵌套的预加载你可以使用 . 语法来加载嵌套的关联。比如,让我们在一个 Eloquent 语句中一次加载所有书籍的作者以及作者的死人通讯簿: get();
预加载约束有时候你可能希望预加载一些关联,但是也需要对预加载查询指定额外的约束,这里有个示例: function ($query) {
$query->where('title','%first%');
}])->get();
在这个例子中, function ($query) {
$query->orderBy('created_at','desc');
}])->get();
延迟预加载有时候你可能需要在上层模型被获取后才预加载其关联。当你需要来动态决定是否加载关联模型时尤其有用: if ($someCondition) {
$books->load('author','publisher'); } 如果你需要对预加载做一些查询约束,你可以传递 load(['author' => function ($query) {
$query->orderBy('published_date','asc');
}]);
插入关系模型Save 方法
'A new comment.']);
$post = AppPost::find(1); $post->comments()->save($comment); 注意上面我们并没有使用关联模型的动态属性的方式来访问 如果你需要一次添加多个关联模型,你需要使用 $post->comments()->saveMany([
new AppComment(['message' => 'A new comment.']),new AppComment(['message' => 'Another comment.']),]); Save & 多对多关联当与多对多关联互动时, roles()->save($role,['expires' => $expires]);
Create 方法除了 $comment = $post->comments()->create([
'message' => 'A new comment.',]); 在使用 更新从属关联模型当更新一个 $user->account()->associate($account);
$user->save(); 当删除 account()->dissociate();
$user->save(); 多对多关联附加 / 抽离当使用多对多关联时,Eloquent 提供了一些额外的帮助方法来更方便的管理关联模型。比如,让我们想象一下用户可以有很多角色并且角色可以有很多用户。你可以使用 $user->roles()->attach($roleId);
当附加关联到模型时,你也可以传递一个含有额外数据的数组来将其添加到中间表中: roles()->attach($roleId,['expires' => $expires]);
当然,有时候你可能需要从用户中删除一个角色。你可以使用 roles()->detach($roleId);
// Detach all roles from the user... 为了更加的便捷, $user->roles()->detach([1,3]);
$user->roles()->attach([1 => ['expires' => $expires],3]); 更新中间表的记录如果你需要更新中间表中存在的行,你可以使用 $user->roles()->updateExistingPivot($roleId,$attributes);
便利的同步你也可以使用 roles()->sync([1,3]);
你也可以同时传递额外的中间表的键值对: roles()->sync([1 => ['expires' => true],3]);
联动上层模型时间戳当一个模型 namespace App;
use IlluminateDatabaseEloquentModel; class Comment extends Model
/**
现在,当你更新 $comment->text = 'Edit to this comment!'; $comment->save(); 以上就是laravel学习教程之关联模型的全部内容,希望对大家学习php有所帮助。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |