Laravel 反对原生的 SQL 查问、晦涩的查问结构器 和 Eloquent ORM 三种查问形式:

  • 晦涩的查问结构器(简称DB),它是为创立和运行数据库查问提供的一个接口,反对大部分数据库操作,和手写SQL 的实质是一样的。
  • Eloquent ORM(简称ORM),是一个对象关系映射(Object Relational Mapper)工具,通过建设模型与数据表进行交互,它会把数据库中的数据映射成对象和汇合对象,无需接触底层数据,能够间接调用映射进去的对象进行开发。

这篇笔记次要来整顿下罕用的ORM 操作。

查问

artisan tinker 是 Laravel 框架自带的命令,用以调出 Laravel 的交互式运行时,Eloquent ORM 的代码能够间接在该环境中运行。

查问列表

获取所有数据:

use App\Models\User;$users = User::all();

如果只须要局部字段,有两种形式进行限定:

$users = User::all(["id", "name"]);$users = User::select("id", "name")->get();

获取单列:

$name = User::pluck('name');// ["boo", "mac", "yumi"]

还能够在返回的汇合中指定字段的自定义键名,留神:该自定义键必须是该表的其它字段列名,否则会报错:

$name = User::pluck('email','name');// ["boo" => "boo@example.com", "yumi" => "yumi@example.com"]

查问单条数据

// 通过主键获取模型$user = User:;find(1);// 获取匹配查问条件的第一个模型$user = User::where('is_enable', 1)->first();// 获取第一条数据的指定列值$user = User::value("name");  // 返回后果是字符串:boo// 传递主键数组来调用 find 办法,返回匹配记录汇合$user = User::find([1,2,3]);  // 等同于 $user = User::whereIn("id", [1,2,3])->get();

解决返回后果集

Eloquent ORM 查问返回值是 Illuminate\Database\EloquentCollection 的一个实例,所以除了能够应用传统的数组形式进行遍历,还能够应用汇合形式进行遍历。

chunk

chunk办法能够把大的后果集分成小块查问,例如,咱们能够将全副User 表数据切割成一次解决 5 条记录的一小块:

$result = User::chunk(5, function ($users) {    foreach ($users as $user) {        echo $user->name.PHP_EOL;    }});// result 为 boolean 

在User表中一共有14条数据,通过查看查问日志,能够看到chunk 分了三次查问 :

each

如果想对一个汇合中的每一项都进行一些操作,但不批改汇合自身,则能够应用each

$users = User::all();$users = $users->each(function ($user , $key) {    $user->password = bcrypt(122410);});// 返回后果蕴含残缺的User模型,其中password 字段的值被批改

map

如果想对汇合中的所有元素进行迭代,对它们进行批改,并返回蕴含批改的新汇合,那么须要应用map

$users = User::all();$users = $users->map(function ($user, $key) {    return [        "name" => $user->name,        "password" => bcrypt(122410),    ];});// 返回后果仅蕴含name 和password 字段,其中password 字段的值被批改

聚合办法

// 统计总数$count = User::count();// 统计分组$count = User::select(User::raw("count(id) as aggregate"))->groupBy("is_enable")->get();// 留神不能这样写:User::select('count(id) as aggregate')->groupBy("is_enable")->get();

条件查问

构建简单查问:

// 组合查问形式一$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();// 两种形式的查问SQL 是一样的: select `id`, `name` as `username`, `email` from `users` where (`is_enable` = '1' and (`id` > '10' or `name` like '%admin%'))// Where Exists$builder = User::select("id", "name", "email");$builder->whereExists(function ($query){    $query->select(User::raw("title"))        ->from("topics")        ->whereRaw("topics.user_id = users.id");});

排序

// 用户id 倒序$user = User::orderBy("id", "desc")->get();// 获取created_at 最大的一条记录$user = User::latest()->first();// 获取created_at 最小的一条记录$user = User::oldest()->first();// 随机一条记录$users = User::inRandomOrder()->first();

限定

// 跳过前两条记录,取三条记录$users = User::skip(2)->take(3)->get();// 输入SQL:select * from `users` limit 3 offset 2  // 同上$users = User::offset(2)->limit(3)->get();

其余

// 应用别名$user = User::select("name as username", "id")->first();// 创立一个查问构建器$builder = User::select("name");// 增加一个查问列到已存在的 select 子句$user = $builder->addSelect("id")->first();

分页

$users = User::paginate(10);$users = User::simplePaginate(10);
  1. paginate 办法,返回Illuminate\Pagination\LengthAwarePaginator实例
  2. simplePaginate 办法,返回Illuminate\Pagination\Paginator实例

每个分页器实例都能够通过以下办法提供更多分页信息:

$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)

插入

$user = new User();$user->name = "yumi";$user->fill(["email" => "yumi@example.com"]);$user->save();// 返回模型对象$result = User::create(    ["name"=>"boo", 'email' => 'boo@example.com']);// 返回模型对象$result = User::insert(    ["name"=>"boo", 'email' => 'boo@example.com']);// 返回Boolean$result = User::insertGetId(    ["name"=>"boo", 'email' => 'boo@example.com']);// 返回插入记录对应ID

更新

单个更新

$user = User::find(1);$user->name = 'yumi';$user->save();// 返回Boolean$user = User::where("id", 1)->update(['password' => bcrypt(122410)]);// 返回受影响行数

批量更新:

$user = User::whereIn("id", [1,2,3])->update(['password' => bcrypt(122410)]); // 返回受影响行数

删除

单个删除

// 通过主键查问,删除模型$user = User::find(1);$user->delete();// 返回Boolean// 间接通过主键删除User::destroy(1);// 返回受影响行数User::where('id', 1)->delete();

批量删除:

User::destroy([1, 2, 3]);User::destroy(1, 2, 3);// 注:通过 Eloquent 批量删除时,deleting 和 deleted事件不会被触发,因为在进行模型删除时不会获取模型。User::whereIn('id', [1, 2, 3])->delete();// 均返回受影响行数

软删除

除了实在删除数据库记录,Eloquent 也能够「软删除」模型。软删除的模型并不是真的从数据库中删除了。 事实上,是在模型上设置了 deleted_at 属性并将其值写入数据库。如果 deleted_at 值非空,代表这个模型已被软删除。

如果要开启模型软删除性能,须要在模型上应用 Illuminate\Database\Eloquent\SoftDeletes trait,同时须要增加 $dates 属性:

<?phpnamespace 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 字段。同时,查问进去的后果也会主动排除已被软删除的记录。

软删除常见操作

// 验证给定的模型实例是否已被软删除if ($user->trashed()) {    //}// 包含已软删除的模型$users = User::withTrashed()->get();            // 只检索软删除模型           $users = User::onlyTrashed()->get();// 永恒删除$user->forceDelete(); 

留神⚠️:

  1. 通过 Eloquent 批量删除时,deleting 和 deleted 事件不会被触发,因为在进行模型删除时不会获取模型。
  2. 通过 Eloquent 批量更新时,更新的模型不会触发 saving, saved, updating 和 updated 模型事件。这是因为在批量更新时实际上从未检索模型。

参考链接

  • Eloquent 疾速入门
  • Laravel 中Eloquent ORM 相干操作