Laravel Eloquent ORM 經常使用操做整理

Laravel 支持原生的 SQL 查詢、流暢的查詢構造器 和 Eloquent ORM 三種查詢方式:php

  • 流暢的查詢構造器(簡稱DB),它是爲建立和運行數據庫查詢提供的一個接口,支持大部分數據庫操做,和手寫SQL 的本質是同樣的。
  • Eloquent ORM(簡稱ORM),是一個對象關係映射(Object Relational Mapper)工具,經過創建模型與數據表進行交互,它會把數據庫中的數據映射成對象和集合對象,無需接觸底層數據,能夠直接調用映射出來的對象進行開發。

這篇筆記主要來整理下經常使用的ORM 操做。laravel

查詢

artisan tinker 是 Laravel 框架自帶的命令,用以調出 Laravel 的交互式運行時,Eloquent ORM 的代碼能夠直接在該環境中運行。數據庫

查詢列表

獲取全部數據:segmentfault

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

若是隻須要部分字段,有兩種方式進行限定:數組

$users = User::all(["id", "name"]);

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

獲取單列:app

$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 的一個實例,因此除了可使用傳統的數組方式進行遍歷,還可使用集合方式進行遍歷。dom

chunk

chunk方法能夠把大的結果集分紅小塊查詢,例如,咱們能夠將所有User 表數據切割成一次處理 5 條記錄的一小塊:工具

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

在User表中一共有14條數據,經過查看查詢日誌,能夠看到chunk 分了三次查詢 :ui

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 屬性:

<?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 字段。同時,查詢出來的結果也會自動排除已被軟刪除的記錄。

軟刪除常見操做

// 驗證給定的模型實例是否已被軟刪除
if ($user->trashed()) {
    //
}

// 包括已軟刪除的模型
$users = User::withTrashed()->get();
            
// 只檢索軟刪除模型           
$users = User::onlyTrashed()->get();

// 永久刪除
$user->forceDelete();

注意⚠️:

  1. 經過 Eloquent 批量刪除時,deleting 和 deleted 事件不會被觸發,由於在進行模型刪除時不會獲取模型。
  2. 經過 Eloquent 批量更新時,更新的模型不會觸發 saving, saved, updating 和 updated 模型事件。這是由於在批量更新時實際上從未檢索模型。

參考連接

相關文章
相關標籤/搜索