iT邦幫忙

2026 iThome 鐵人賽

DAY 18
0
自我挑戰組

Laravel 讀碼源系列 第 18

鋼琴留言版的MODEL

  • 分享至 

  • xImage
  •  

鋼琴留言版
https://laihao.vaserver.com/gbook

可以實際測試
也歡迎大家一起來學習喔
https://www.pressplay.cc/project/9D489B43D08BD198FDEB03ECDEFAC161/about

資料表-這裡只有單一一個

MVC架構-
MODEL
前端
後端

--
MODEL程式碼

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class Gbook extends Model
{
    protected $connection = 'mysql_gbook';
    protected $table = 'gbook';
    protected $primaryKey = 'gid';
    public $timestamps = false;
    
    protected $fillable = [
        'gbook_poser',
        'gbook_kind', 
        'gbook_title',
        'gbook_msg',
        'gbook_date',
    ];
}

這是一個 Laravel 的 Eloquent Model,名稱是 Gbook,用來代表資料庫中的 gbook 資料表。透過它,你可以使用 PHP 物件方式新增、查詢、修改及刪除留言資料。

1. 命名空間

namespace App\Models;

表示這個 Model 位於:

app/Models/Gbook.php

Laravel 會使用命名空間來管理類別,避免不同類別名稱互相衝突。

例如 Controller 中通常可以這樣引用:

use App\Models\Gbook;

2. 引入 Eloquent Model

use Illuminate\Database\Eloquent\Model;

這行引入 Laravel 的基礎 Eloquent Model。

class Gbook extends Model

表示 Gbook 繼承 Laravel 的 Model 類別,因此可以使用:

Gbook::all();
Gbook::find(1);
Gbook::create([...]);
Gbook::where(...)->get();

Eloquent 原本預設會按照 Model 名稱推測資料表與主鍵;這裡因為資料表和主鍵名稱不是 Laravel 的預設格式,所以需要自行設定。

3. 指定資料庫連線

protected $connection = 'mysql_gbook';

表示這個 Model 不使用 Laravel 的預設資料庫連線,而是使用名為 mysql_gbook 的連線設定。

這個名稱通常必須存在於:

config/database.php

例如:

'connections' => [

    'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'database' => env('DB_DATABASE'),
        'username' => env('DB_USERNAME'),
        'password' => env('DB_PASSWORD'),
    ],

    'mysql_gbook' => [
        'driver' => 'mysql',
        'host' => env('GBOOK_DB_HOST', '127.0.0.1'),
        'port' => env('GBOOK_DB_PORT', '3306'),
        'database' => env('GBOOK_DB_DATABASE'),
        'username' => env('GBOOK_DB_USERNAME'),
        'password' => env('GBOOK_DB_PASSWORD'),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'strict' => false,
    ],
],

.env 可以搭配:

GBOOK_DB_HOST=127.0.0.1
GBOOK_DB_PORT=3306
GBOOK_DB_DATABASE=laihao_my_gbook
GBOOK_DB_USERNAME=資料庫帳號
GBOOK_DB_PASSWORD=資料庫密碼

因此,這個 Model 很適合用來連接「獨立的留言資料庫」或「不同資料庫伺服器」。

Laravel 的 Eloquent 支援在 Model 上指定不同的資料庫連線名稱。 laravel

4. 指定資料表

protected $table = 'gbook';

指定這個 Model 對應的資料表是:

gbook

如果沒有這一行,Laravel 會根據 Gbook 自動推測資料表名稱。通常會推測成:

gbooks

但實際資料表是單數的 gbook,所以必須明確指定。

例如:

Gbook::all();

大致會產生類似 SQL:

SELECT * FROM `gbook`;

5. 指定主鍵

protected $primaryKey = 'gid';

指定資料表的主鍵欄位是:

gid

Laravel Eloquent 預設假設主鍵名稱是:

id

但你的資料表使用:

gid

因此要加上這一行。

有了這個設定,以下查詢才會正確使用 gid

$gbook = Gbook::find(2);

它會尋找:

SELECT *
FROM `gbook`
WHERE `gid` = 2
LIMIT 1;

如果沒有設定 $primaryKey = 'gid',Laravel 可能會錯誤地查詢:

WHERE `id` = 2

6. 關閉 Laravel 自動時間欄位

public $timestamps = false;

Laravel Eloquent 預設會尋找兩個欄位:

created_at
updated_at

新增或修改資料時,Laravel 也會嘗試自動更新它們。

但你的 gbook 資料表沒有這兩個欄位,只有:

gbook_date

因此設定:

public $timestamps = false;

告訴 Laravel:

不要自動處理 created_atupdated_at

否則新增資料時可能出現類似錯誤:

Unknown column 'updated_at' in 'field list'

Laravel 官方文件也說明,如果資料表沒有標準的 created_atupdated_at 欄位,就可以將 $timestamps 設定為 falselaravel

要注意的是,這只會關閉 Laravel 的自動時間管理,不會讓 gbook_date 自動失效。

你的 MySQL 資料表仍然有:

gbook_date TIMESTAMP
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP

所以:

  • 新增資料時,MySQL 可以自動設定 gbook_date
  • 修改資料時,MySQL 可以自動更新 gbook_date

7. $fillable 欄位白名單

protected $fillable = [
    'gbook_poser',
    'gbook_kind', 
    'gbook_title',
    'gbook_msg',
    'gbook_date',
];

$fillable 是 Eloquent 的「可大量填入欄位白名單」。

它會限制哪些欄位可以透過以下方式批次寫入:

Gbook::create($data);

或:

gbook->update(data);

目前允許寫入的欄位包括:

欄位 用途
gbook_poser 發表人
gbook_kind 發表類型或程度
gbook_title 標題或分類
gbook_msg 留言內容
gbook_date 發表日期

gid 沒有放入 $fillable,因此一般不會讓使用者透過批次提交資料時自行指定主鍵,這是比較安全的做法。

Laravel 使用 $fillable 是為了防止 Mass Assignment,也就是避免使用者透過表單額外提交不應該修改的欄位。 laravel

8. 新增資料範例

Gbook::create([
    'gbook_poser' => '學生',
    'gbook_kind' => '初級',
    'gbook_title' => '許願',
    'gbook_msg' => '卡農',
]);

這會新增一筆資料。

由於沒有指定 gbook_date,資料庫的:

DEFAULT CURRENT_TIMESTAMP

會自動產生日期。

大致相當於:

INSERT INTO gbook
(
    gbook_poser,
    gbook_kind,
    gbook_title,
    gbook_msg
)
VALUES
(
    '學生',
    '初級',
    '許願',
    '卡農'
);

gid 也會由 MySQL 的 AUTO_INCREMENT 自動產生。

9. 查詢資料範例

查詢全部留言:

$messages = Gbook::all();

查詢單筆留言:

$message = Gbook::find(1);

查詢「許願」:

$messages = Gbook::where('gbook_title', '許願')
                 ->orderByDesc('gbook_date')
                 ->get();

查詢內容包含「兒歌」的資料:

$messages = Gbook::where('gbook_msg', 'like', '%兒歌%')
                 ->get();

分頁查詢:

$messages = Gbook::orderByDesc('gbook_date')
                 ->paginate(10);

10. 修改資料

$message = Gbook::findOrFail(2);

$message->update([
    'gbook_msg' => '德布西:月光',
]);

這裡的 2gid

修改後:

  • Laravel 不會自動寫入 created_atupdated_at
  • MySQL 會依照欄位設定,自動更新 gbook_date

11. 刪除資料

$message = Gbook::findOrFail(2);
$message->delete();

大致相當於:

DELETE FROM gbook
WHERE gid = 2;

如果只是希望查詢而不真正刪除,則需要另外設計軟刪除欄位,例如 deleted_at;目前這份資料表並沒有這個欄位。

12. 這段程式與資料表的對應

Gbook Model
    ↓
mysql_gbook 資料庫連線
    ↓
gbook 資料表
    ↓
gid 主鍵
    ↓
gbook_poser、gbook_kind、gbook_title、
gbook_msg、gbook_date 欄位

設定完成後,Laravel 就能正確對應你前面 SQL 中的資料表。

13. 可考慮的改進

使用日期欄位時加入 $casts

可以加入:

protected $casts = [
    'gbook_date' => 'datetime',
];

完整範例:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Gbook extends Model
{
    protected $connection = 'mysql_gbook';

    protected $table = 'gbook';

    protected $primaryKey = 'gid';

    public $timestamps = false;

    protected $fillable = [
        'gbook_poser',
        'gbook_kind',
        'gbook_title',
        'gbook_msg',
        'gbook_date',
    ];

    protected $casts = [
        'gbook_date' => 'datetime',
    ];
}

這樣讀取時:

$message->gbook_date

會被 Laravel 轉成日期物件,方便格式化:

$message->gbook_date->format('Y-m-d H:i');

若日期完全交給 MySQL

如果新增時一律讓 MySQL 自動產生 gbook_date,也可以不把它放進 $fillable

protected $fillable = [
    'gbook_poser',
    'gbook_kind',
    'gbook_title',
    'gbook_msg',
];

這樣使用者不能透過表單自行偽造留言日期,安全性較高。

總結

這個 Gbook Model 的主要功能是把 Laravel 和你的 gbook 資料表接起來:

protected $connection = 'mysql_gbook';

使用指定的資料庫連線。

protected $table = 'gbook';

對應 gbook 資料表。

protected $primaryKey = 'gid';

指定 gid 為主鍵。

public $timestamps = false;

停用 Laravel 預設的 created_atupdated_at 管理。

protected $fillable = [...]

指定哪些欄位可以使用 create()update() 批次寫入。

因此,這份程式可以安全地支援留言的新增、查詢、修改和刪除。

明天就來解釋後端程式碼~


上一篇
解釋鋼琴留言版的資料表
下一篇
鋼琴留言版的後端 程式碼
系列文
Laravel 讀碼源22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言