Laravel 系列 - 2: 與資料庫的互動

更新於 發佈於 閱讀時間約 1 分鐘

這篇文章將帶你了解 Laravel 與資料庫之間的互動方式。

Model 的建立與操作

在許多專案中,當資料庫需要與應用程式互動時,我們通常會建立資料庫模型(Model),以方便後續的操作。透過模型,我們可以輕鬆進行資料庫的 CRUD 操作,並進一步設置環境配置、添加額外註解,以及提高專案的可維護性,讓後來的開發者能夠更順利地接手。

那麼,該如何建立模型呢?其實過程相當簡單。我們可以透過 artisan 指令來生成模型的基礎框架,然後再根據需求手動調整細節。具體步驟如下:

  1. .env 設定檔中,配置好資料庫的連線參數。
  2. 將資料表的 DDL 資訊複製到 schema 檔案中。[ 註1 ]
  3. 執行指令 php artisan make:model 表位置 --migration 來生成模型及對應的遷移檔案。
  4. 手動調整生成的檔案內容,特別是設定表格名稱、主鍵及其他必要的資料庫設定。[ 註2 ]
  5. 執行指令 php artisan ide-helper:models "App\\Models\\剛剛的表位置",生成 IDE 的輔助提示。
  6. 最後,為模型的屬性加上註解,這樣就大功完成啦!

需要注意的是,Laravel 預設不支援複合主鍵的使用,因此建議可以選擇使用 UUID 來替代複合主鍵的需求。

Model 間的關聯

簡單的關聯 —— 使用 join

在使用 SQL 查詢時,我們通常不會只查詢一張表格,而是會有多張表格需要聯結(join),以便整合出我們需要的資料。在 Laravel 中,這樣的查詢方式也同樣簡單,我們只需要使用 join 指令。

假設我們在組成查詢的 query 時,需要將一張表格左連結(left join)到另一張表格,我們可以直接使用 ->leftJoin() 來實現,並在後面加上相關的條件篩選。舉個例子:

$query->leftJoin('other_table', 'a.id', '=', 'other_table.aid')
->whereIn('other_table.status', $myArray);

這樣就能在查詢中左連結 other_table,並使用條件過濾結果。

複雜的關聯 —— 使用 Eloquent 來處理 X 對 X 關係

當資料庫中有一些經常使用的表格關聯,每次撰寫查詢時都需要重複建立連結,這樣的做法容易變得繁瑣。此時,我們可以選擇在模型層定義好這些關聯,這樣就不需要每次都寫 join,只需在查詢時直接調用關聯即可。

在前面提到的模型建立過程中,我們可以在模型內定義各種資料表之間的關聯,比如一對一、一對多、多對一以及多對多等關係。這些關聯定義好後,當我們在取得資料時,就可以自動獲取與這筆資料相關聯的其他資料。舉例來說:

// 模型定義
class A extends Model
{
// 假設 A 對 B 是一對多關係
public function children(): HasMany
{
return $this->hasMany(B::class);
}
}

// 別處使用時
$myChildren = A::find(1)->children; //這樣就能取得 A 模型關聯的 B 模型資料

使用 Eloquent 關聯的注意事項

這種方式非常方便,但需要注意的是,關聯式資料表適合每個資料表各司其職且資料不冗餘,並且關聯資料通常是每次查詢時都會需要的。如果不是這樣的情況,過多的關聯可能會讓查詢變得過於複雜且性能不佳。

因此,若是某些關聯並非每次都需要,建議還是使用 join 的方式來動態建立查詢,這樣可以避免不必要的資料提取,保持查詢效率。

N + 1 問題

N + 1 問題是 ORM 中常見的一個性能問題,當資料庫查詢不當時,可能會導致系統效能顯著下降。

簡單來說,N + 1 問題會發生在當模型之間存在一對多關係,並且系統的架構設計不夠完善時,例如資料表中的欄位設計不夠精簡、關聯不夠嚴謹等情形。具體來說,每當你查詢一筆資料時,系統會額外去查詢 N 筆關聯資料,這樣會導致資料庫的負擔大幅增加,從而影響效能。

範例說明

假設有一個顧客(User)模型,並且顧客擁有多筆消費紀錄(BuyLog)。首先查詢顧客資料(1 筆),然後對每一筆顧客資料都再發送一次查詢來獲取對應的消費紀錄(N 筆)。結果會導致總共執行 1 + N 次查詢,從而加重資料庫的負擔,進而影響效能。

// 顧客模型
class User extends Model
{
public function buyLogs()
{
return $this->hasMany(BuyLog::class);
}
}
//當我們使用以下程式碼查詢所有顧客及其消費紀錄時,可能會遇到 N + 1 問題:
$users = User::all();

foreach ($users as $user) {
echo $user->buyLogs;
}

解決方案

為了避免 N + 1 問題,我們可以採取以下兩種主要的解決方案:

  1. 使用 join 查詢
    我們可以使用 join 查詢來一次性取得顧客和其消費紀錄的資料,這樣可以減少資料庫的查詢次數,從而提高效能。例如:
    $users = User::select('users.*')
    ->leftJoin('buy_logs', 'users.id', '=', 'buy_logs.user_id')
    ->get();
    這樣,資料庫只會發送一次查詢來獲取顧客及其相關的消費紀錄,避免了重複的查詢。
  2. 使用 eager loading(預載入)
    Laravel 提供了 with() 方法來進行預載入(eager loading),可以一次性載入所有關聯資料,從而避免發生 N + 1 問題。使用方法如下:
    $users = User::with('buyLogs')->get();
    這樣,Laravel 會使用兩次查詢來加載所有顧客及其消費紀錄:一次查詢顧客資料,另一次查詢所有消費紀錄。這樣可以顯著減少查詢次數,避免每次顧客資料載入時再去查詢相關的消費紀錄。
  3. 使用緩存
    除了改善查詢邏輯,另一種解決方法是將不常變動的資料緩存起來。對於那些查詢頻繁但變動不大的資料,我們可以使用 Laravel 的緩存機制,將資料儲存在緩存中,避免重複查詢資料庫。例如,可以使用 cache 函數來緩存資料:
    $users = Cache::remember('users_with_buy_logs', 60, function () {
    return User::with('buyLogs')->get();
    });
    這樣查詢結果會被緩存 60 分鐘,在此期間不會再次查詢資料庫。這對於讀取頻繁且變動不大的資料來說,是一種非常有效的優化方式喔!

[ 註1 ] 複製 DDL 資訊後,記得檢查最上方的 CREATE DATABASE 語句,並將其調整為 CREATE DATABASE IF NOT EXISTS '表名稱'。這樣可以避免每次啟動應用程式時都重新建立同名資料表。

[ 註2 ] 如果需要,這時候你也可以在模型中加入軟刪除(Soft Deletes)的設定。詳細資訊請參見 Laravel 官方文檔

參考資料

  1. https://tools.wingzero.tw/article/sn/527
  2. https://inbound.technology/lavarel中如何建立資料庫/
  3. https://ithelp.ithome.com.tw/articles/10243718
  4. https://laravel.com/api/8.x/Illuminate/Database/Eloquent/SoftDeletes.html
  5. https://laravel.com/docs/10.x/eloquent-relationships#introduction
留言
avatar-img
留言分享你的想法!
avatar-img
林柏宇的沙龍
2會員
51內容數
test
林柏宇的沙龍的其他內容
2025/04/27
JWT(JSON Web Token)是基於 JSON 格式的開放標準,主要用於身份驗證與權限確認。本文介紹了JWT的基本結構,並闡述其特點,如降低資料庫壓力、靈活性及無狀態性。JWT 特別適用於分佈式系統。本篇將協助讀者深入理解 JWT 的重要性與實際應用。
Thumbnail
2025/04/27
JWT(JSON Web Token)是基於 JSON 格式的開放標準,主要用於身份驗證與權限確認。本文介紹了JWT的基本結構,並闡述其特點,如降低資料庫壓力、靈活性及無狀態性。JWT 特別適用於分佈式系統。本篇將協助讀者深入理解 JWT 的重要性與實際應用。
Thumbnail
2025/04/20
本文介紹了容器的基本概念、組成部分以及其在應用開發中的重要性,特別是對初階和高階工程師的影響。透過深入探討容器的優點,以及Docker、Kubernetes和ArgoCD等相關技術,幫助讀者理解容器化的應用與管理,進而簡化開發過程並提高效率。適合對容器技術感興趣的開發者從零開始學習與掌握。
Thumbnail
2025/04/20
本文介紹了容器的基本概念、組成部分以及其在應用開發中的重要性,特別是對初階和高階工程師的影響。透過深入探討容器的優點,以及Docker、Kubernetes和ArgoCD等相關技術,幫助讀者理解容器化的應用與管理,進而簡化開發過程並提高效率。適合對容器技術感興趣的開發者從零開始學習與掌握。
Thumbnail
2025/04/13
本文探討自動化測試的核心理念與實際應用,涵蓋如何模擬運行環境、確保程式碼在各種情境下的穩定性,以及進行錯誤處理的方法。文中指出自動化測試的各種優點,並提到設計測試的注意事項。透過使用相關工具和方法,讀者可以有效進行功能測試,並掌握相關技巧以應對常見問題,讓開發過程更為順利。
Thumbnail
2025/04/13
本文探討自動化測試的核心理念與實際應用,涵蓋如何模擬運行環境、確保程式碼在各種情境下的穩定性,以及進行錯誤處理的方法。文中指出自動化測試的各種優點,並提到設計測試的注意事項。透過使用相關工具和方法,讀者可以有效進行功能測試,並掌握相關技巧以應對常見問題,讓開發過程更為順利。
Thumbnail
看更多
你可能也想看
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
CodeIgniter 3 和 Laravel 是兩種不同的 PHP 框架,各有其特點和適用場景。CodeIgniter 3 是一個輕量級框架,Laravel 是一個功能強大的現代 PHP 框架,同樣都有Models的它們有什麼樣的差別呢?
Thumbnail
CodeIgniter 3 和 Laravel 是兩種不同的 PHP 框架,各有其特點和適用場景。CodeIgniter 3 是一個輕量級框架,Laravel 是一個功能強大的現代 PHP 框架,同樣都有Models的它們有什麼樣的差別呢?
Thumbnail
這一章節旨在介紹 PHP 中的物件導向編程(OOP)概念。通過詳細講解類別、建構子、訪問修飾符(公開、私有、受保護)、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda 表達式、泛型和反射等概念,使讀者能夠理解和應用這些 OOP 技術來編寫更具結構性和可維護性的 PHP 代碼。
Thumbnail
這一章節旨在介紹 PHP 中的物件導向編程(OOP)概念。通過詳細講解類別、建構子、訪問修飾符(公開、私有、受保護)、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda 表達式、泛型和反射等概念,使讀者能夠理解和應用這些 OOP 技術來編寫更具結構性和可維護性的 PHP 代碼。
Thumbnail
※ 視圖模板 視圖模板(View Templates) 是在 MVC 架構中負責展示數據的 HTML 文件,包含模板語法,用於在渲染時插入實際數據。它們的主要目的是分離數據與展示邏輯,讓代碼更加模塊化和易於維護。 視圖模板設計和使用的核心理念,就是「重複的事情不要重複做、效益最大化、有效利用資源
Thumbnail
※ 視圖模板 視圖模板(View Templates) 是在 MVC 架構中負責展示數據的 HTML 文件,包含模板語法,用於在渲染時插入實際數據。它們的主要目的是分離數據與展示邏輯,讓代碼更加模塊化和易於維護。 視圖模板設計和使用的核心理念,就是「重複的事情不要重複做、效益最大化、有效利用資源
Thumbnail
軟體系統的發展歷程大多相似,首重解決基本需求、提供操作介面,進而提升安全性、擴充功能、優化操作。
Thumbnail
軟體系統的發展歷程大多相似,首重解決基本需求、提供操作介面,進而提升安全性、擴充功能、優化操作。
Thumbnail
在使用laravel中的Queue job的時候 如果希望job中斷還可以重新啟動這個時候就會需要用到Supervisor了 本篇文章為您帶來如何使用Supervisor執行Laravel的queue:work的教學
Thumbnail
在使用laravel中的Queue job的時候 如果希望job中斷還可以重新啟動這個時候就會需要用到Supervisor了 本篇文章為您帶來如何使用Supervisor執行Laravel的queue:work的教學
Thumbnail
有的時候,會希望在物件導向中對原生的Class新增功能的時候,大多我們都會寫一個新的class並繼承。 但是其實Laravel提供了一個不同的方式,讓我們可以在常用的Class上,直接新增想要的function,那就是macro。
Thumbnail
有的時候,會希望在物件導向中對原生的Class新增功能的時候,大多我們都會寫一個新的class並繼承。 但是其實Laravel提供了一個不同的方式,讓我們可以在常用的Class上,直接新增想要的function,那就是macro。
Thumbnail
有趣的是,Model 其實沒什麼嚴格的定義,所以每個人對 Model 的解讀也不盡相同,有人覺得資料怎麼儲存屬於 Model 的一部份 (受 ORM 工具的影響),有人覺得工作流程 (workflow) 是 Model 的一部份,我個人也有自己的想法,而且隨專案的規模和特性,也不是總是一樣的。
Thumbnail
有趣的是,Model 其實沒什麼嚴格的定義,所以每個人對 Model 的解讀也不盡相同,有人覺得資料怎麼儲存屬於 Model 的一部份 (受 ORM 工具的影響),有人覺得工作流程 (workflow) 是 Model 的一部份,我個人也有自己的想法,而且隨專案的規模和特性,也不是總是一樣的。
Thumbnail
第一份正職工作 在iot公司擔任後端工程師,一上工就使用先前沒用過的php/laravel,也馬上負責公司產品的架構規劃,先前資料庫只有簡單記載使用者跟使用者的一些設定,很多地方有資料不一致的問題,產品內容還有很多實體的關係沒有被定義進資料庫都是這次改版我要做的事情。 改版納入公司、機器
Thumbnail
第一份正職工作 在iot公司擔任後端工程師,一上工就使用先前沒用過的php/laravel,也馬上負責公司產品的架構規劃,先前資料庫只有簡單記載使用者跟使用者的一些設定,很多地方有資料不一致的問題,產品內容還有很多實體的關係沒有被定義進資料庫都是這次改版我要做的事情。 改版納入公司、機器
Thumbnail
※ 基本操作:SQL 語法,SELECT, WHERE, CREATE, UPDATE, DELETE。 SELECT:從資料庫中或資料表中指定要選擇的欄位中取得資料,稱之為查詢 (query)。 ※ 語法:要由兩部分構成,第一部分是要 "拿什麼" 資料 (若有多項用逗號隔開);第二部分則為
Thumbnail
※ 基本操作:SQL 語法,SELECT, WHERE, CREATE, UPDATE, DELETE。 SELECT:從資料庫中或資料表中指定要選擇的欄位中取得資料,稱之為查詢 (query)。 ※ 語法:要由兩部分構成,第一部分是要 "拿什麼" 資料 (若有多項用逗號隔開);第二部分則為
Thumbnail
Laravel的Model是資料和邏輯的核心連接,簡化資料庫操作。本指南著重於Model的基本屬性、方法和Eloquent ORM的使用。我們詳細探討了hasMany、hasOne和belongsTo這些關聯,它們基於外鍵確定資料間的關係。透過本文,您將深入了解如何有效地在Laravel中使用Mod
Thumbnail
Laravel的Model是資料和邏輯的核心連接,簡化資料庫操作。本指南著重於Model的基本屬性、方法和Eloquent ORM的使用。我們詳細探討了hasMany、hasOne和belongsTo這些關聯,它們基於外鍵確定資料間的關係。透過本文,您將深入了解如何有效地在Laravel中使用Mod
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News