laravel orm進行增刪改查


 https://laravelacademy.org/post/9699.html

建議用DB門面直接操作數據庫,因為ORM性能低。數據查詢上面,ORM不會比DB差的,就比如with,是用了sql最基本的拆語句優化。ORM的損耗僅僅是代碼層面的,這已經不算是問題了。

ORM適用於一般到中等復雜度的查詢,也適用於各種模型操作,比如有一個關系targets,你可以直接用targets()->delete()等等進行關系數據操作。
ORM中的軟刪除,自動更新時間字段,字段保護,字段類型轉換,都會在一些規范而且系統的工程中讓你受益。

另外DB的場景:一些比較復雜的查詢語句,事務操作,等都需要DB來完成。

模型類定義
使用模型類之前,需要在數據庫有對應的數據表,因為模型類就是數據表在面向對象編程語言中的映射。比如我們前面幾篇教程中用到的 User 模型和 Post 模型都是這樣,要創建一個模型類,需要使用 make:model 命令:

php artisan make:model Post
注:如果對應的數據表尚未創建,你還可以在創建模型類的同時創建對應的數據庫遷移文件,通過 php artisan make:model Post -m 即可。如果你想將模型類創建到 app/Models 目錄下,可以這么運行上述命令 php artisan make:model Models/Post。

接下來我們就是 posts 表映射的 Post 模型為例,來看看默認都有哪些約定。新生成的 Post 模型類如下:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    //
}
里面什么東西都沒有,但是我們就可以通過它完成數據表記錄的增刪改查操作了,怎么做到的?這就是「約定優於配置」的功勞了。下面我們就來看看這些默認的約定。

表名
Eloquent 約定模型類映射表名是將類名由駝峰格式轉化為小寫+下划線(含多個單詞的話),最后將其轉化為復數形式,比如 Post 對應表名是 posts、PostTag 對應表名是 post_tags 等等。當然,如果你不想遵循這個系統約定的規則,也可以通過手動設置模型類屬性的方式進行自定義,例如:

protected $table = 'articles';
主鍵
Eloquent 默認假設每張數據表都有一個整型的自增主鍵,其字段名為 id,如果你的數據表主鍵名不是 id,可以通過 $primaryKey 屬性來指定:

protected $primaryKey = 'post_id';
如果主鍵不是自增的,還可以設置 $incrementing 屬性為 falsepublic $incrementing = false;
如果主鍵不是整型,還可以設置 $keyType 屬性為 stringprotected $keyType = 'string';
時間戳
Eloquent 默認約定每張表都有 created_at 和 updated_at 字段(遷移類中 $table->timestamps() 會生成這兩個字段),並且在保存模型類時會自動維護這兩個字段。如果你的數據表里面不包含這兩個字段,或者只包含一個,都需要設置 $timestamps 屬性為 falsepublic $timestamps = false;
或者通過 CREATED_AT 和 UPDATED_AT 常量來設置自定義的創建和更新時間字段:

public const CREATED_AT = 'create_time';
public const UPDATED_AT = 'update_time';
此外,默認時間的存儲格式是 Y-m-d H:i:s,你還可以通過 $dateFormat 屬性來自定義時間戳的格式,該屬性值通過 PHP 的 date() 函數進行解析,所以原則上支持 date 函數支持的所有語法格式,比如將時間設置為 Unix 時間戳:

protected $dateFormat = 'U';
這樣,保存到數據庫的時間格式就是 Unix 時間戳了,前提是你的 created_at 和 updated_at 字段是整型,否則會報格式錯誤。

數據庫連接
Eloquent 模型類默認約定的數據庫連接是 config/database.php 中配置的默認連接,正如我們在連接配置教程中所說的那樣,如果應用配置了多個數據庫連接,可以通過 $connection 屬性為模型類指定使用哪個連接:

protected $connection = 'connection_name';
查詢數據
日常開發中,大部分操作都是數據庫中查詢數據,Eloquent 模型了為我們提供了很多方法幫助我們從數據庫中獲取數據。

獲取所有記錄
我們可以通過模型類提供的 all 方法獲取一張表的所有記錄:

$posts = Post:all();
和查詢構建器一樣,該方法返回的也是集合,只不過是模型類集合:



要獲取指定模型類的字段屬性,遍歷該集合即可:

foreach ($posts as $post) {
    dump($post->title);
}
和查詢構建器一樣,如果結果集很大的話,模型類也支持通過 chunk 方法分塊獲取查詢結果:

Post::chunk(10, function ($posts) {
   foreach ($posts as $post) {
       if ($post->views == 0) {
           continue;
       } else {
           dump($post->title . ':' . $post->views);
       }
   }
});
除此之外,在 Eloquent 模型中還可以通過 cursor 方法每次只獲取一條查詢結果,從而最大限度減少內存消耗:

foreach (Post::cursor() as $post) {
    dump($post->title . ':' . $post->content);
}
獲取指定查詢結果
如果想要指定查詢條件和查詢字段,可以通過 where 方法和 select 方法來實現:

$posts = Post::where('views', '>', 0)->select('id', 'title', 'content')->get();
對應查詢結果如下:



實際上,Eloquent 模型類底層的查詢也是基於查詢構建器來實現的,你可以在模型類上調用所有查詢構建器的 Where 查詢方法,同樣是以流接口的模式構建方法鏈調用即可。前面提到的 chunk 和 cursor 方法也適用於這種指定查詢條件的查詢操作。

因為是查詢構建器,所以我們還可以在模型查詢操作中對查詢結果進行排序和分頁:

$posts = Post::where('views', '>', 0)->orderBy('id', 'desc')->offset(10)->limit(5)->get();
對應的返回結果如下:



獲取單條記錄
當然,你也可以通過查詢構建器的方式在模型類查詢中獲取單條記錄:

$user = User::where('name', '學院君')->first();
返回的結果是一個模型類實例:



你可以直接通過 $user->name 這樣的方式訪問模型類實例的屬性。

此外,如果查詢的條件是主鍵 ID 的話,還可以將上述調用簡化為通過 find 方法來實現:

$user = User::find(1);
返回結果與上面完全一致。

模型類查詢結果為空會返回 null。如果你想要在單條記錄返回結果為空時返回 404 響應(在控制器方法中可能需要用到類似操作),可以通過 firstOrFail 或者 findOrFail 方法在找不到對應記錄時拋出 404 異常,從而簡化代碼編寫:

$user = User::findOrFail(111);
如果 id=111 的記錄在 users 數據表中不存在,就會返回 404 響應:



獲取聚合結果
Eloquent 模型類同樣支持 count、sum、avg、maxmin 等聚合函數查詢:

$num = User::whereNotNull('email_verified_at')->count();       # 計數     
$sum = User::whereNotNull('email_verified_at')->sum('id');     # 求和    
$avg = User::whereNotNull('email_verified_at')->avg('id');     # 平均值   
$min = User::whereNotNull('email_verified_at')->min('id');     # 最小值   
$max = User::whereNotNull('email_verified_at')->max('id');     # 最大值   
你會發現,如果你掌握了查詢構建器,就等同於掌握了 Laravel 中的所有數據庫查詢操作。只不過將 DB::table 換成對應的模型類而已。

注:除獲取單條記錄之外,ELoquent 模型類查詢返回的結果都是集合類,因此你可以在查詢結果上調用集合類的所有方法,還可以自定義模型對應集合類,詳情請查看對應官方文檔。

插入數據
通過 Eloquent 模型類插入記錄到數據庫也比較簡單:

$post = new App\Post;
$post->title = '測試文章標題';
$post->content = '測試文章內容';
$post->user_id = 1;
$post->save();
創建時間和更新時間字段由 Eloquent 底層自動幫我們維護(遵循默認約定的話)。執行上面的代碼就會在數據庫新增一條記錄(我們在 Tinker 中執行上述代碼):



我們先要創建一個新的 Post 模型實例,然后依次設置需要設置的字段,最后調用 save 方法保存即可。

此外,Eloquent 還為我們提供了一些快捷的插入方法,比如 firstOrCreate 和 firstOrNew,這兩個方法都會先嘗試通過指定查詢條件在數據庫中查找對應記錄,如果沒有找到的話,會創建對應模型類的實例,並將查詢條件作為對應字段值設置到模型屬性上。兩者的區別是 firstOrCreate 方法在設置完模型屬性后會將該模型記錄保存到數據庫中,而 firstOrNew 不會:

$post_1 = Post::firstOrCreate([
    'title' => '測試文章標題1',
    'user_id' => 1,
]);

$post_2 = Post::firstOrNew([
    'title' => '測試文章標題1',
    'user_id' => 1,
]);
不過學院君倒不建議這么做,感覺還是分開寫代碼可讀性更好一些,也方便自己去處理一些異常情況。

更新數據
通過模型類更新數據表記錄也很簡單:

$post = Post::find(31);
$post->title = '測試文章標題更新';
$post->save();
更新時間 Eloquent 底層會自動幫我們維護,執行上面的代碼即可完成該 $post 模型對應數據表記錄的更新:



同樣,Eloquent 也為我們提供了快捷的更新方法 updateOrCreate,該方法首先會根據傳入參數對模型對應記錄進行更新,如果發現對應記錄不存在,則會將更新數據作為初始數據插入數據庫,並保存(同樣也不建議這么做,除非你的場景特別適合):

$user = user::updateOrCreate(
    ['name' => '學院君'],
    ['email' => 'admin@laravelacademy.org']
);
有的時候我們可能需要批量更新模型對應數據表的多條記錄,這可以借助查詢構建器來實現:

Post::where('views', '>', 0)->update(['views' => 100]);
刪除數據
通過模型類刪除對應數據表記錄和更新記錄類似,都要先獲取對應操作模型實例,刪除對應記錄更簡單,獲取到模型實例后,直接調用其刪除方法即可:

$post = Post::find(31);
$post->delete();
這樣,就完成了 id = 31 對應數據表記錄的刪除,你還可以通過 Eloquent 提供的 destroy 方法一次刪除多條記錄,通過數組傳遞多個主鍵 ID 即可:

Post::destroy([1,2,3]);
當然,你也可以通過查詢構建器的方式刪除指定記錄:

$user = User::where('name', '學院君')->fisrt();
$user->delete();
結語
在這篇教程中,我們簡單給大家介紹了 Eloquent 是什么,以及「約定優於配置」理念在 Eloquent 中的應用,最后還給大家演示了如何通過 Eloquent 實現數據庫的增刪改查,當然,Eloquent 的功能遠不僅如此,還支持很多強大的功能,比如批量賦值、軟刪除、查詢作用域設置、模型事件、關聯關系等,下一篇教程開始學院君將帶領大家來逐一了解這些高階功能。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM