Laravel 支持原生的 SQL 查询、流畅的查询构造器 和 Eloquent ORM 三种查询方式:
- 流畅的查询构造器(简称DB),它是为创建和运行数据库查询提供的一个接口,支持大部分数据库操作,和手写SQL 的本质是一样的。
- Eloquent ORM(简称ORM),是一个对象关系映射(Object Relational Mapper)工具,通过建立模型与数据表进行交互,它会把数据库中的数据映射成对象和集合对象,无需接触底层数据,可以直接调用映射出来的对象进行开发。
这篇笔记主要来整理下常用的ORM 操作。
查询
artisan tinker
是 Laravel 框架自带的命令,用以调出 Laravel 的交互式运行时,Eloquent ORM 的代码可以直接在该环境中运行。
查询列表
获取所有数据:
1 2
| use App\Models\User; $users = User::all();
|
如果只需要部分字段,有两种方式进行限定:
1 2 3
| $users = User::all(["id", "name"]);
$users = User::select("id", "name")->get();
|
获取单列:
1 2
| $name = User::pluck('name');
|
还可以在返回的集合中指定字段的自定义键名,注意:该自定义键必须是该表的其它字段列名,否则会报错:
1 2
| $name = User::pluck('email','name');
|
查询单条数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $user = User:;find(1);
$user = User::where('is_enable', 1)->first();
$user = User::value("name");
$user = User::find([1,2,3]);
$user = User::whereIn("id", [1,2,3])->get();
|
处理返回结果集
Eloquent ORM 查询返回值是 Illuminate\Database\EloquentCollection
的一个实例,所以除了可以使用传统的数组方式进行遍历,还可以使用集合方式进行遍历。
chunk
chunk
方法可以把大的结果集分成小块查询,例如,我们可以将全部User 表数据切割成一次处理 5
条记录的一小块:
1 2 3 4 5 6
| $result = User::chunk(5, function ($users) { foreach ($users as $user) { echo $user->name.PHP_EOL; } });
|
在User表中一共有14
条数据,通过查看查询日志,可以看到chunk
分了三次查询 :
each
如果想对一个集合中的每一项都进行一些操作,但不修改集合本身,则可以使用each
:
1 2 3 4 5
| $users = User::all(); $users = $users->each(function ($user , $key) { $user->password = bcrypt(122410); });
|
map
如果想对集合中的所有元素进行迭代,对它们进行修改,并返回包含修改的新集合,那么需要使用map
:
1 2 3 4 5 6 7 8
| $users = User::all(); $users = $users->map(function ($user, $key) { return [ "name" => $user->name, "password" => bcrypt(122410), ]; });
|
聚合方法
1 2 3 4 5 6
| $count = User::count();
$count = User::groupBy("is_enable")->selectRaw("count(id) as aggregate")->get();
|
条件查询
构建复杂查询:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| $where = []; $where[] = ["is_enable", 1]; $where[] = [ function($query){ $query->where("id", ">", 10) ->orWhere("name", "like", "%admin%"); }]; User::select("id", "name as username", "email")->where($where)->get();
$builder = User::select("id", "name as username", "email"); $builder->where("is_enable", 1); $builder->where(function ($query){ $query->where("id", ">", 10) ->orWhere("name", "like", "%admin%"); }); $users = $builder->get();
$builder = User::select("id", "name", "email"); $builder->whereExists(function ($query){ $query->select(User::raw(1)) ->from("topics") ->whereRaw("topics.user_id = users.id"); });
|
排序
1 2 3 4 5 6 7 8 9 10 11
| $user = User::orderBy("id", "desc")->get();
$user = User::latest()->first();
$user = User::oldest()->first();
$users = User::inRandomOrder()->first();
|
限定
1 2 3 4 5 6
| $users = User::skip(2)->take(3)->get();
$users = User::offset(2)->limit(3)->get();
|
其他
1 2 3 4 5 6 7
| $user = User::select("name as username", "id")->first();
$builder = User::select("name");
$user = $builder->addSelect("id")->first();
|
分页
1 2
| $users = User::paginate(10); $users = User::simplePaginate(10);
|
paginate
方法,返回Illuminate\Pagination\LengthAwarePaginator
实例
simplePaginate
方法,返回Illuminate\Pagination\Paginator
实例
每个分页器实例都可以通过以下方法提供更多分页信息:
1 2 3 4 5 6 7 8 9 10 11
| $result->count() // 当前页条数 $result->currentPage() // 当前页码 $result->perPage() // 每页多少条 $result->total() // 总数(使用simplePaginate 时无效) $result->hasMorePages() // 是否有更多 $result->firstItem() $result->lastItem() $result->lastPage() (使用simplePaginate 时无效) $result->nextPageUrl() $result->previousPageUrl() $result->url($page)
|
插入
单条插入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| $user = new User(); $user->name = "yumi"; $user->fill(["email" => "yumi@example.com"]); $user->save();
$user = new User( ["name"=>"boo", 'email' => 'boo@example.com'] ); $user->save();
$result = User::create( ["name"=>"boo", 'email' => 'boo@example.com'] );
$result = User::insertGetId( ["name"=>"boo", 'email' => 'boo@example.com'] );
|
批量插入:
1 2 3 4 5
| $result = User::insert([ ["name"=>"boo", 'email' => 'boo@example.com'] ["name"=>"yumi", 'email' => 'yumi@example.com'] ]);
|
注意⚠️:此时不会触发saving、saved 模型事件
更新
单条更新
1 2 3 4 5 6 7 8 9 10 11
| $user = User::find(1); $user->name = 'yumi'; $user->save();
$user = User::find(1); $user->update($data);
$user = User::where("id", 1)->update(['password' => bcrypt(122410)]);
|
批量更新:
1 2
| $user = User::whereIn("id", [1,2,3])->update(['password' => bcrypt(122410)]);
|
删除
单个删除
1 2 3 4 5 6 7 8 9 10
| $user = User::find(1); $user->delete();
User::destroy(1);
User::where('id', 1)->delete();
|
批量删除:
1 2 3 4 5 6 7
| User::destroy([1, 2, 3]);
User::destroy(1, 2, 3);
User::whereIn('id', [1, 2, 3])->delete();
|
软删除
除了真实删除数据库记录,Eloquent 也可以「软删除」模型。软删除的模型并不是真的从数据库中删除了。 事实上,是在模型上设置了 deleted_at
属性并将其值写入数据库。如果 deleted_at
值非空,代表这个模型已被软删除。
如果要开启模型软删除功能,需要做好三件事情:
- 数据库增加
deleted_at
字段
- 在模型上导入
Illuminate\Database\Eloquent\SoftDeletes
特征
- 同时将
deleted_at
列添加到 $dates
属性
1 2 3 4 5 6 7 8 9 10 11 12 13
| <?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model { use SoftDeletes; protected $dates = ['deleted_at']; }
|
现在,当在模型实例上使用 delete
方法,当前日期时间会写入 deleted_at
字段。同时,查询出来的结果也会自动排除已被软删除的记录。
软删除常见操作
1 2 3 4 5 6 7 8 9 10 11 12 13
| if ($user->trashed()) { }
$users = User::withTrashed()->get();
$users = User::onlyTrashed()->get();
$user->forceDelete();
|
注意⚠️:
- 通过 Eloquent 批量删除时,deleting 和 deleted 事件不会被触发,因为在进行模型删除时不会获取模型。
- 通过 Eloquent 批量更新时,更新的模型不会触发 saving, saved, updating 和 updated 模型事件。这是因为在批量更新时实际上从未检索模型。
参考链接