【整理】Laravel中Eloquent ORM 关联关系的操作
Laravel中Eloquent ORM 关联关系的操作
关联数据
定义关联关系
一对一
<?php
class User extends Model{// 获取关联到用户的手机public function phone(){// Phone 模型默认有一个 user_id 外键return $this->hasOne('App\Phone'); // 外键应该在父级上有一个与之匹配的id(或者自定义 $primaryKey)// return $this->hasOne('App\Phone', 'foreign_key');// 用User的local_key,匹配Phone的foreign_key// return $this->hasOne('App\Phone', 'foreign_key', 'local_key');}
}$phone = User::find(1)->phone; // 获取用户的手机模型
相对的关联
<?php
class Phone extends Model {// 获取手机对应的用户public function user(){return $this->belongsTo('App\User');// return $this->belongsTo('App\User', 'foreign_key');// return $this->belongsTo('App\User', 'foreign_key', 'other_key');}
}$user = Phone::find(1)->user; // 查询phone的id=1对应的user
$user = Phone::where('number','188**')->first()->user; // 查询电话为188的用户
一对多
class User extends Model{// 获取文章public function article(){return $this->hasMany('App\Comment');// return $this->hasMany('App\Comment', 'foreign_key');// return $this->hasMany('App\Comment', 'foreign_key', 'local_key');}
}
$articles = User::find(1)->article; // 返回 userid为1 的所有文章
$article = User::find(1)->article()->where('title', 'aa')->first(); // 返回某一篇
一对多(逆向)
class Article extends Model{public function user(){return $this->belongsTo('App\User');// return $this->belongsTo('App\Post', 'foreign_key');// return $this->belongsTo('App\Post', 'foreign_key', 'other_key');}
}
$user = Article::find($id)->user; // 返回文章的作者
多对多
需要三张数据表:users、roles 和 role_user,
role_user 表为关系表,默认按照关联模型名的字母顺序命名,并且包含 user_id 和 role_id 两个列。
class User extends Model{/*** 用户角色*/public function roles(){//默认去role_user查找关系// return $this->belongsToMany('App\Role');return $this->belongsToMany('App\Role',"role_users");// 定义键值// return $this->belongsToMany('App\Role', 'user_roles', 'user_id', 'role_id');}
}$roles = User::find(1)->roles;
// 返回 [{"id":1,"name":"SuperManager","pivot":{"user_id":1,"role_id":1}},{"id":2,"name":"Manager","pivot":{"user_id":1,"role_id":2}}]$roles = User::find(1)->roles()->orderBy('name')->get(); // 条件约束
注意我们获取到的每一个 Role 模型都被自动赋上了 pivot 属性。该属性包含一个代表中间表的模型,并且可以像Eloquent 模型一样使用。
如果你的 pivot 表包含额外的属性,必须在定义关联关系时进行指定:
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
如果你想要你的 pivot 表自动包含created_at 和 updated_at 时间戳,在关联关系定义时使用 withTimestamps 方法:
return $this->belongsToMany('App\Role')->withTimestamps();
过中间表字段过滤关联关系
return $this->belongsToMany('App\Role')->wherePivot('approved', 1);
return $this->belongsToMany('App\Role')->wherePivotIn('priority', [1, 2]);
关联查询
存在的关联查询
// 获取所有至少有一条评论的文章...
$posts = App\Post::has('comments')->get();
你还可以指定操作符和数目来自定义查询:// 获取所有至少有三条评论的文章...
$posts = Post::has('comments', '>=', 3)->get();
还可以使用”.“来构造嵌套 has 语句,例如,你要获取所有至少有一条评论及投票的文章:// 获取所有至少有一条评论获得投票的文章...
$posts = Post::has('comments.votes')->get();
如果你需要更强大的功能,可以使用 whereHas 和 orWhereHas 方法将 where 条件放到 has 查询上,这些方法允许你添加自定义条件约束到关联关系条件约束,例如检查一条评论的内容:// 获取所有至少有一条评论包含foo字样的文章
$posts = Post::whereHas('comments', function ($query) {$query->where('content', 'like', 'foo%');
})->get();
无关联结果查询
// 获取所有没有评论的博客文章
$posts = App\Post::doesntHave('comments')->get();// 检查评论内容:
$posts = Post::whereDoesntHave('comments', function ($query) {$query->where('content', 'like', 'foo%');
})->get();
统计关联模型
如果你想要在不加载关联关系的情况下统计关联结果数目,可以使用 withCount 方法,该方法会放置一个 {relation}_count 字段到结果模型
$posts = App\Post::withCount('comments')->get();
foreach ($posts as $post) {echo $post->comments_count;
}// 添加约束条件到查询一样来添加多个关联关系的“计数”:
$posts = Post::withCount(['votes', 'comments' => function ($query) {$query->where('content', 'like', 'foo%');
}])->get();
echo $posts[0]->votes_count;
echo $posts[0]->comments_count;// 为关联关系计数结果设置别名,从而允许在一个关联关系上进行多维度计数:$posts = Post::withCount(['comments','comments AS pending_comments' => function ($query) {$query->where('approved', false);}
])->get();echo $posts[0]->comments_count;
echo $posts[0]->pending_comments_count;
渴求式加载
当以属性方式访问数据库关联关系的时候,关联关系数据是“懒惰式加载”的,这意味着关联关系数据直到第一次访问的时候才被加载。
$books = App\Book::all();
foreach ($books as $book) {echo $book->author->name;
}
// 该循环要执行26次查询:1次是获取书本身,剩下的25次查询是为每一本书获取其作者。
$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, ...)
渴求式加载多个关联关系
$books = App\Book::with('author', 'publisher')->get();
嵌套的渴求式加载
// 加载所有书的作者及所有作者的个人联系方式:
$books = App\Book::with('author.contacts')->get();
带条件约束的渴求式加载
// 加载 title 包含 first 的文章
$users = App\User::with(['posts' => function ($query) {$query->where('title', 'like', '%first%');
}])->get();// 加载按created_at倒序的的文章
$users = App\User::with(['posts' => function ($query) {$query->orderBy('created_at', 'desc');
}])->get();
懒惰渴求式加载
$books = App\Book::all();
if ($someCondition) {$books->load('author', 'publisher');
}
// 设置更多的查询条件到渴求式加载查询上,可以传递一个闭包到 load 方法:$books->load(['author' => function ($query) {$query->orderBy('published_date', 'asc');
}]);
插入 & 更新关联模型
save 方法
$comment = new App\Comment(['message' => 'A new comment.']);
$post = App\Post::find(1);
$post->comments()->save($comment);
// save 方法会自动添加 post_id 值到新的Comment 模型。
保存多个关联模型,可以使用 saveMany 方法:
$post = App\Post::find(1);
$post->comments()->saveMany([new App\Comment(['message' => 'A new comment.']),new App\Comment(['message' => 'Another comment.']),
]);
create方法
该方法接收属性数组、创建模型、然后插入数据库。save 和 create 的不同之处在于 save 接收整个 Eloquent 模型实例而 create 接收原生 PHP 数组:
使用 create 方法之前确保先浏览属性批量赋值文档。
$post = App\Post::find(1);
$comment = $post->comments()->create(['message' => 'A new comment.',
]);
从属关联关系
更新 belongsTo 关联, 使用associate 方法,该方法会在子模型设置外键:
$account = App\Account::find(10);
$user->account()->associate($account);
$user->save();
移除 belongsTo 关联的时候,使用dissociate 方法。该方法会设置关联关系的外键为 null:
$user->account()->dissociate();
$user->save();
多对多关联 的 附加/分离
假定一个用户可能有多个角色,同时一个角色属于多个用户,要通过在连接模型的中间表中插入记录附加角色到用户上,可以使用 attach 方法:
$user = App\User::find(1);
$user->roles()->attach($roleId);// 以数组形式传递额外被插入数据到中间表:
$user->roles()->attach($roleId, ['expires' => $expires]);
移除一个多对多关联记录,使用 detach 方法。detach 方法将会从中间表中移除相应的记录;
但是,两个模型在数据库中都保持不变:
// 从指定用户中移除角色...
$user->roles()->detach($roleId);// 从指定用户移除所有角色...
$user->roles()->detach();
接收数组形式的 ID 作为输入:
$user = App\User::find(1);
$user->roles()->detach([1, 2, 3]);
$user->roles()->attach([1 => ['expires' => $expires], 2, 3]);
同步关联
sync 方法接收数组形式的 ID 并将其放置到中间表
// 任何不在该数组中的 ID 对应记录将会从中间表中移除
$user->roles()->sync([1, 2, 3]);// 还可以和 ID 一起传递额外的中间表值:
$user->roles()->sync([1 => ['expires' => true], 2, 3]);// 如果不想要脱离存在的ID,可以使用syncWithoutDetaching 方法:
$user->roles()->syncWithoutDetaching([1, 2, 3]);
切换关联
// 如果当前没有附加,则附加:如果给定ID当前被附加,则取消附加
$user->roles()->toggle([1, 2, 3]);
在中间表上保存额外数据
// 接收额外中间表属性数组作为第二个参数:
App\User::find(1)->roles()->save($role, ['expires' => $expires]);
更新中间表记录 updateExistingPivot
// 更新中间表中已存在的行,接收中间记录外键和属性数组进行更新
$user = App\User::find(1);
$user->roles()->updateExistingPivot($roleId, $attributes);
触发父级时间戳
当一个模型属于另外一个时,子模型更新时父模型的时间戳也被更新将很有用
例如,当 Comment 模型被更新时,你可能想要”触发“更新其所属模型 Post 的updated_at 时间戳。Eloquent 使得这项操作变得简单,只需要添加包含关联关系名称的 touches 属性到子模型即可:
class Comment extends Model{// 触发的所有关联关系protected $touches = ['post'];// 关联关系public function post(){return $this->belongsTo('App\Post');}
}
更新 Comment 时,所属模型 Post 将也会更新其 updated_at 值
$comment = App\Comment::find(1);
$comment->text = 'Edit to this comment!';
$comment->save();
【整理】Laravel中Eloquent ORM 关联关系的操作相关推荐
- 解决laravel框架中Eloquent ORM的save方法无法插入数据的问题
学习laravel中: 今天在测试使用Eloquent ORM将数据使用 save()方法插入到mysql中时,出现了错误,如图所示: 在网上查阅资料后找到了原因: 使用save方法新增数据: lar ...
- laravel中的ORM模型修改created_at,updated_at,deleted_at三个时间字段类型
laravel框架中的ORM模型极大的简化了数据库操作,同时也提高了数据操作安全性. 在laravel框架ORM模型中默认会有三个时间字段,created_at,updated_at,deleted_ ...
- Laravel之Eloquent ORM
一.ORM编程思想 1.1 Active Record 设计模式 Active Record 是一种数据访问设计模式,它可以帮助你实现数据对象Object到关系数据库的映射.应用Active Reco ...
- Laravel 的 Eloquent ORM学习
创建模型 首先,创建一个 Eloquent 模型,生成的模型通常放在 app 目录中,但你可以通过 composer.json 随意地将它们放在可被自动加载的地方.所有的 Eloquent 模型都继承 ...
- Laravel之Eloquent ORM访问器调整器及属性转换
一.查询构建器的get方法 查询构建器的get方法返回了一个集合$users = App\User::where('active', 1)->get(); foreach ($users as ...
- 在ECSHOP中使用laravel框架的orm组件 简化ecshop的二次开发
在长期的 ecshop二次开发中 我慢慢喜欢上了简单的php开发模式!可能是因为我最早是做前端开发的 ,php+smarty这种简单的组合让我更喜欢!要实现什么功能 只需要写个函数在 includes ...
- Laravel 5.1 文档攻略——Laravel Eloquent ORM最强大也是最难理解的部分:数据关系...
简介 其实大家都知道,数据表之间都是可以关联的,Eloquent ORM是数据模型操作代替表操作,那么表的关联查询,在Eloquent这里也就是模型间的关联查询,这就是本章的主要内容: Eloquen ...
- php orm 内存泄漏,Lavarel Eloquent ORM常驻进程下的内存溢出问题
Laravel 的 Eloquent ORM 提供了漂亮.简洁的 ActiveRecord 实现来和数据库交互.每个数据库表都有一个对应的「模型」用来与该表交互.你可以通过模型查询数据表中的数据,并将 ...
- Laravel 中查询 where 记录
Laravel 的 Eloquent 使用 Between $query->whereBetween('age',[$from,$to]) 这是生成 And between ... and .. ...
最新文章
- python时间序列分析航空旅人_时间序列分析-ARIMA模型(python)
- Kali Linux 安全渗透教程第四更1.3 Kali Linux简介
- 致力推广Vim的那个程序员走了,Vim之父:我要把9.0版献给他
- java pdfbox2 中文乱码,如何从PDFBox 2.0.2中的PDDocument提取字体
- 单人存档_电子发票归档怎么保存稳当?电子发票存档你都会了吗?
- 纵有倚天剑还要屠龙刀,实现Power BI报表服务器自定义认证
- Lua5.2中的全局环境
- 物联网(IoT)的11大云平台:AWS、Azure、谷歌云、Oracle、
- GitKraKenSetup工具——小章鱼
- [LeetCode] Remove Duplicates from Sorted List 移除有序链表中的重复项
- 面对人生这道程序,该如何编码?
- httpclient发布application/octet-stream
- 拍摄完的图片怎么添加水印?这两个方法简单又有效
- 按Right-BICEP的测试用例
- SX126x-数字接口SPI和控制功能
- 小游戏---2048
- 效率(1)Excel常用操作技巧
- 贝索斯证词:零售业不是赢家通吃,亚马逊天天在竞争
- Bellon(多么痛的领悟)
- 狡兔三窟,在搜狐也开了一个博客