您现在的位置是:网站首页 > 心得笔记
laravel框架中简单的模型关联
1.1、一对一
模型说明:一个 User 模型关联一个 Phone 模型
两种关联方式:
1、正向关联 hasOne
在 User 模型中写一个 phone 方法,在 phone 方法内部调用 hasOne 方法并返回其结果:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 获得与用户关联的电话记录。
*/
public function phone()
{
return $this->hasOne('App\Phone','user_id','id');
/*重要技巧!!!!
第一个参数是关联模型的类名
第二个参数 foreign_key 是使用的外键名 Eloquent 会基于模型名决定外键名称 User模型对应外键user_id
第三个参数 local_key 是自定义键名
*/
}
}
2、反向关联 belongsTo
我们已经能从 User 模型访问到 Phone 模型了。现在,再在 Phone 模型中定义一个关联,此关联能让我们访问到拥有此电话的 User 模型。这时,使用的是与 hasOne 方法对应的 belongsTo 方法:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Phone extends Model
{
/**
* 获得拥有此电话的用户。
*/
public function user()
{
return $this->belongsTo('App\User','user_id','id');
/*重要技巧!!!!
第一个参数是关联模型的类名
第二个参数 foreign_key 是使用的外键名 通过检查关系方法的名称并使用 _id 作为后缀名来确定默认外键名称
第三个参数 local_key 是自定义键名
*/
}
}
1.2、一对多
模型说明:一个 Post 模型关联一个 Comment 模型
两种关联方式:
1、正向关联 hasMany
一篇博客文章可能会有无限多条评论。就像其它的 Eloquent 关联一样,一对多关联的定义也是在 Eloquent 模型中写一个方法:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/**
* 获得此博客文章的评论。
*/
public function comments()
{
return $this->hasMany('App\Comment','post_id','id');
/*重要技巧!!!!
第一个参数是关联模型的类名
第二个参数 foreign_key 是使用的外键名 父级模型名加上 _id 后缀名作为外键字段
第三个参数 local_key 是自定义键名
*/
}
}
2、反向关联 belongsTo
我们已经能获得一篇文章的所有评论,接着再定义一个通过评论获得所属文章的关联。这个关联是 hasMany 关联的反向关联,在子级模型中使用 belongsTo 方法定义它:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
/**
* 获得此评论所属的文章。
*/
public function post()
{
return $this->belongsTo('App\Post','post_id','id');
/*重要技巧!!!!
第一个参数是关联模型的类名
第二个参数 foreign_key 是使用的外键名 默认外键名是 Eloquent 依据关联方法名、并在关联名后加上 _id 后缀确定的
第三个参数 local_key 是自定义键名 父级模型的主键
*/
}
}
关联模型计数
如果想要只计算关联结果的统计数量而不需要真实加载它们,可以使用 withCount
方法,它将放在结果模型的 {relation}_count
列。示例如下:
$posts = App\Post::withCount('comments')->get();foreach ($posts as $post) { echo $post->comments_count;}
可以像给查询添加限制一样为多个关系添加「计数」:
$posts = App\Post::withCount(['votes', 'comments' => function ($query) { $query->where('content', 'like', 'foo%');}])->get();echo $posts[0]->votes_count;echo $posts[0]->comments_count;
还可以给关联计数结果起别名,这允许你在同一关联上添加多个计数:
$posts = App\Post::withCount([ 'comments', 'comments as pending_comments_count' => function ($query) { $query->where('approved', false); }])->get();echo $posts[0]->comments_count;echo $posts[0]->pending_comments_count;
如果将 withCount
和 select
查询组装在一起,请确保在 select
方法之后调用 withCount
:
$query = App\Post::select(['title', 'body'])->withCount('comments');echo $posts[0]->title;echo $posts[0]->body;echo $posts[0]->comments_count;
预加载
当以属性方式访问 Eloquent 关联时,关联数据「懒加载」。这着直到第一次访问属性时关联数据才会被真实加载。不过 Eloquent 能在查询父模型时「预先载入」子关联。预加载可以缓解 N + 1 查询问题。为了说明 N + 1 查询问题,考虑 Book
模型关联到 Author
的情形:
<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Book extends Model{ /** * 获取书籍作者。 */ public function author() { return $this->belongsTo('App\Author'); }}
现在,我们来获取所有的书籍及其作者:
$books = App\Book::all();foreach ($books as $book) { echo $book->author->name;}
此循环将执行一个查询,用于获取全部书籍,然后为每本书执行获取作者的查询。如果我们有 25 本书,此循环将运行 26 个查询:1 个用于查询书籍,25 个附加查询用于查询每本书的作者。
谢天谢地,我们能够使用预加载将操作压缩到只有 2 个查询。在查询时,可以使用 with
方法指定想要预加载的关联:
$books = App\Book::with('author')->get();foreach ($books as $book) { echo $book->author->name;}
在这个例子中,仅执行了两个查询:
select * from books select * from authors where id in (1, 2, 3, 4, 5, ...)
预加载多个关联
有时,你可能需要在单一操作中预加载几个不同的关联。要达成此目的,只要向 with
方法传递多个关联名称构成的数组参数:
$books = App\Book::with(['author', 'publisher'])->get();
嵌套预加载
可以使用 「点」 语法预加载嵌套关联。比如在一个 Eloquent 语句中预加载所有书籍作者及其联系方式:
$books = App\Book::with('author.contacts')->get();
预加载指定列
并不是总需要获取关系的每一列。在这种情况下,Eloquent 允许你为关联指定想要获取的列:
$users = App\Book::with('author:id,name')->get();
{note} 在使用这个特性时,一定要在要获取的列的列表中包含
id
列。
为预加载添加约束
有时,可能希望预加载一个关联,同时为预加载查询添加额外查询条件,就像下面的例子:
$users = App\User::with(['posts' => function ($query) { $query->where('title', 'like', '%first%');}])->get();
在这个例子中, Eloquent 将仅预加载那些 title
列包含 first
关键词的文章。也可以调用其它的 查询构造器 方法进一步自定义预加载操作:
$users = App\User::with(['posts' => function ($query) { $query->orderBy('created_at', 'desc');}])->get();
{note} 在约束预加载时,不能使用
limit
和take
查询构造器方法。
上一篇:Git快速入门