2025年11月13日 星期四

laravel 12 Eloquent ORM-Query Builder

一、簡潔比較 Raw SQL、Query Builder 與 Eloquent(以 Laravel 生態為背景)。
每一項都列出主要優點與缺點,並在最後給出適用情境建議。

        (1) Raw SQL(原生 SQL)
優點:
性能最佳:可撰寫最直接、最優化的查詢(例如複雜 JOIN、窗口函數、子查詢、特定索引提示)。
完全控制:可以使用資料庫專屬語法、函數與最佳化技巧,無抽象限制。
可重現/可移植於非 ORM 環境:不依賴框架抽象,任何 DB client 都能執行。
缺點:
開發速度慢:查詢需手寫,維護成本高,重複性代碼易增加。
可讀性差:複雜查詢不易閱讀與理解。
安全風險:若未妥善綁定參數,易遭 SQL injection。
測試與重構不便:欄位或表名變動需手動追蹤修改。

        (2) Query Builder(查詢建構器,例:Laravel Query Builder)
優點:
平衡性能與便利性:比 Eloquent 更接近 SQL、執行效率高但仍提供連鎖式 API 增進可讀性。
防注入:內建參數綁定,安全性高。
易讀且可組合:動態建立查詢(條件分支、分頁、排序)容易。
更接近 SQL 行為:對複雜查詢比 ORM 更靈活。
缺點:
還是需要理解 SQL:對非常複雜的 DB 特性仍可能受限或變得冗長。
無模型層:返回通常是陣列/物件而非 rich model(未自帶關聯、事件、屬性存取器等)。
中等抽象:在大量業務邏輯與資料操作時,可能需要自行封裝重複邏輯。
適用情境(簡述)
要動態組合查詢、追求效能但想保留較好可讀性時使用。

        (3) Eloquent(ActiveRecord ORM,例:Laravel Eloquent)
優點
開發速度快:以模型表示資料表,能用物件式語法操作資料(create, update, relations)。
高可讀性與可維護性:關聯、訪問器、事件、scope、mutator 等功能使商業邏輯集中在 Model。
生態整合:與框架遷移、驗證、序列化、資源(Resource)等配合良好。
適合快速原型與中等複雜度應用:提高生產力。
缺點
性能開銷:大量關聯查詢或 N+1 問題若不注意會造成效能下降(需 eager loading、精細調整)。
複雜查詢受限:高度複雜或資料庫特有功能時,ORM 生成的 SQL 可能不理想或難以實作。
抽象過度:當資料層行為需要精細調整時,ORM 層可能成為障礙。
隱式行為:例如自動時間戳、大量事件/observer 可能在背景造成意外負擔。

        適用情境(簡述)
CRUD 為主、開發速度與可維護性重於最高性能的應用;團隊偏向領域驅動與物件導向設計。

        總結比較(重點):
1.可控性與效能:Raw SQL > Query Builder > Eloquent(通常)。
2.開發速度與抽象便利性:Eloquent > Query Builder > Raw SQL。
3.安全性(參數綁定預設):Query Builder 與 Eloquent 內建較安全;Raw SQL 需手動綁定。
4.可維護性:Eloquent(關聯與模型封裝)最佳;Raw SQL 最差(除非良好封裝)。

         建議做法(實務折衷)
1.預設使用 Eloquent 來快速開發與維護常見 CRUD 和關聯邏輯,配合 eager loading、scope 與適當的索引避免 N+1 與效能問題。
2.在對效能要求高或需複雜查詢時,改用 Query Builder 以兼顧可讀性與效能。
3.當 Query Builder 仍無法寫出最佳 SQL(或需使用專屬 DB 功能、大查詢最佳化)時,使用 Raw SQL(並務必使用參數綁定與測試)。
4.在專案層面可建立規範:大多數情況用 Eloquent,熱點(Hot path)或報表查詢用 Query Builder/Raw SQL,並把 Raw SQL 封裝至 Repository/Query Class 以利測試與維護。

二、利用Query Builder 在資料庫(DataBase) 插入資料(Data):
1.在Http\Controller\StudentController.php
輸入如下:
   public function addData(){
        DB::table('students')->insert([
        ['name' => 'tester01',
        'email' => 'tester01@gmail.com',
        'age' => 15,
        'date_of_birth' => '2010-01-01',
        'gender' => 'm',
        ],
        ['name' => 'tester02',
        'email' => 'tester02@gmail.com',
        'age' => 15,
        'date_of_birth' => '2010-01-02',
        'gender' => 'f',
        ]
        ]);
        return 'added successfully';
    }

在\routes\web.php 加入
Route::get('add-data',[StudentController::class,'addData']);
如下圖
接下來,下指令 php artisan serve
在網址輸入: http://127.0.0.1:8000/add-data
就會出現 
在資料庫,就會出現

三、利用Query Builder 在資料庫(DataBase) 查詢(fetch)資料(Data):
1.取得全部資料
在Http\Controller\StudentController.php
輸入如下:
    public function getData() {
        $item = DB::table('students')->get();
        return $item;
    }
如下圖:
在\routes\web.php 加入
Route::get('get-data',[StudentController::class,'getData']);
如下圖
接下來,下指令 php artisan serve
在網址輸入: http://127.0.0.1:8000/get-data
就會出現 
2.取得頭一筆
在Http\Controller\StudentController.php
輸入如下:
        public function getDataFirst() {
        $item = DB::table('students')->first();
        return $item;
    }
如下圖:
在\routes\web.php 加入
Route::get('get-data-first',[StudentController::class,'getDataFirst']);
如下圖
接下來,下指令 php artisan serve
在網址輸入: http://127.0.0.1:8000/get-data-first
就會出現
3.取得前面兩筆
在Http\Controller\StudentController.php
輸入如下:
        public function getDataLimit() {
        $item = DB::table('students')
        ->limit(2)
        ->get();
        return $item;
    }
如下圖:
在\routes\web.php 加入
Route::get('get-data-limit',[StudentController::class,'getDataLimit']);
如下圖
接下來,下指令 php artisan serve
在網址輸入: http://127.0.0.1:8000/get-data-limit
就會出現
4.取得指定ID範圍
在Http\Controller\StudentController.php
輸入如下:
    public function getDataWhere() {
        $item = DB::table('students')
        ->where('id','>=',50)
        ->where('id','<=',60)
        ->get();
        return $item;
    }
如下圖:
在\routes\web.php 加入
Route::get('get-data-where',[StudentController::class,'getDataWhere']);
如下圖
接下來,下指令 php artisan serve
在網址輸入: http://127.0.0.1:8000/get-data-where
就會出現


5.取得指定ID的部分欄位
在Http\Controller\StudentController.php
輸入如下:
    public function getDataSelect() {
        $item = DB::table('students')
        ->select('id','name')
        ->where('id',60)
        ->get();
        return $item;
    }
如下圖:
在\routes\web.php 加入
Route::get('get-data-select',[StudentController::class,'getDataSelect']);
如下圖
接下來,下指令 php artisan serve
在網址輸入: http://127.0.0.1:8000/get-data-select
就會出現

四、
利用Query Builder 在資料庫(DataBase) 更新(Update)資料(Data):
1.更新第一筆資料的名字
在Http\Controller\StudentController.php
輸入如下:
    public function updateData() {
        DB::table('students')->where('id',1)->update([
            'name' => 'Updated Name',
        ]);
        return 'Updated Successfully !';
    }
如下圖:
在\routes\web.php 加入
Route::get('update-data',[StudentController::class,'updateData']);
如下圖
接下來,下指令 php artisan serve
在網址輸入: http://127.0.0.1:8000/update-data
就會出現 
在網址輸入: http://127.0.0.1:8000/get-data-first
就會出現

2.更新第一筆資料的名字、年紀、電子郵件
在Http\Controller\StudentController.php
輸入如下:
    public function updateData01() {
        DB::table('students')->where('id',1)->update([
            'name' => 'Updated Name01',
            'age' => 20,
            'email' => 'Updated01@gmail.com',
        ]);
        return 'Updated Successfully !';
    }
如下圖:
在\routes\web.php 加入
Route::get('update-data-01',[StudentController::class,'updateData01']);
如下圖
接下來,下指令 php artisan serve
在網址輸入: http://127.0.0.1:8000/update-data
就會出現 
在網址輸入: http://127.0.0.1:8000/get-data-first
就會出現

五、
利用Query Builder 在資料庫(DataBase) 刪除(Delete)資料(Data):
1.刪除第一筆資料
在Http\Controller\StudentController.php
輸入如下:
    public function deleteData() {
        DB::table('students')->where('id',1)->delete();
        return 'Deleted Successfully !';
    }
如下圖:

在\routes\web.php 加入
Route::get('delete-data',[StudentController::class,'deleteData']);
如下圖
接下來,下指令 php artisan serve
在網址輸入: http://127.0.0.1:8000/delete-data
就會出現 
在網址輸入: http://127.0.0.1:8000/get-data-first
就會出現
1.刪除第90筆以後的資料
在Http\Controller\StudentController.php
輸入如下:
    public function deleteData90() {
        DB::table('students')->where('id','>',90)->delete();
        return 'Deleted Successfully !';
    }

如下圖:
在\routes\web.php 加入
Route::get('delete-data-90',[StudentController::class,'deleteData90']);
如下圖
接下來,下指令 php artisan serve
在網址輸入: http://127.0.0.1:8000/delete-data-90
就會出現 
在網址輸入: http://127.0.0.1:8000/get-data
就會出現

六、利用Query Builder 在資料庫(DataBase) 使用聚合函式(Aggregate Functions):
1.計算資料表 students 有幾筆資料
在Http\Controller\StudentController.php
輸入如下:
    public function getDataCount() {
        $item = DB::table('students')->count();
        return $item;
    }
如下圖:

在\routes\web.php 加入
Route::get('get-data-count',[StudentController::class,'getDataCount']);
如下圖
接下來,下指令 php artisan serve
在網址輸入: http://127.0.0.1:8000/get-data-count
就會出現 

2.計算資料表 students 的欄位age 的最大值
在Http\Controller\StudentController.php
輸入如下:
    public function getDataMax() {
        $item = DB::table('students')->max('age');
        return $item;
    }
如下圖:
在\routes\web.php 加入
Route::get('get-data-max',[StudentController::class,'getDataMax']);
如下圖
接下來,下指令 php artisan serve
在網址輸入: http://127.0.0.1:8000/get-data-max
就會出現 

也可ˇ以在 http://127.0.0.1:8080/phpmyadmin 下SQL指令 
                SELECT * FROM `students` order by `age` desc;
就可以看到欄位age 的最大值

3.計算資料表 students 的欄位age 的最小值
在Http\Controller\StudentController.php
輸入如下:
    public function getDataMin() {
        $item = DB::table('students')->min('age');
        return $item;
    }
如下圖:
在\routes\web.php 加入
Route::get('get-data-min',[StudentController::class,'getDataMin']);
如下圖
接下來,下指令 php artisan serve
在網址輸入: http://127.0.0.1:8000/get-data-min
就會出現 
也可ˇ以在 http://127.0.0.1:8080/phpmyadmin 下SQL指令 
                SELECT * FROM `students` order by `age`;
就可以看到欄位age 的最大值

4.計算資料表 students 的欄位age 的平均值
在Http\Controller\StudentController.php
輸入如下:
    public function getDataAvg() {
        $item = DB::table('students')->avg('age');
        return $item;
    }
如下圖:
在\routes\web.php 加入
Route::get('get-data-avg',[StudentController::class,'getDataAvg']);
如下圖
接下來,下指令 php artisan serve
在網址輸入: http://127.0.0.1:8000/get-data-avg
就會出現 

資料來源:


沒有留言:

張貼留言

Laravel 12 Eloquent 關聯完整指南:從基礎到進階的全方位教學

相關系列文章: 01. 在 windows 10 安裝 laravel 12 studentManagement環境與設定 02. laravel 12 route 路由 03. laravel 12 Blade Templates 網頁模版 04. laravel 12 Con...