鋼琴留言版
https://laihao.vaserver.com/gbook
可以實際測試
也歡迎大家一起來學習喔
https://www.pressplay.cc/project/9D489B43D08BD198FDEB03ECDEFAC161/about
資料庫-這裡只有單一一個
MVC架構-
MODEL
前端
後端
前端-新增內容
程式碼
<!DOCTYPE html>
<html lang="zh-Hant-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>新增許願</title>
<style>
body { font-family: 'Microsoft JhengHei', sans-serif; background: #f9f3ff; }
h1 { text-align: center; color: #6a0dad; margin-top: 30px; }
.form-box { width: 500px; margin: 30px auto; background: white;
padding: 30px; border-radius: 15px;
box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
label { display: block; color: #6a0dad; font-weight: bold; margin-bottom: 5px; }
input[type=text], select, textarea {
width: 100%; padding: 10px; margin-bottom: 15px;
border: 2px solid #e0c8ff; border-radius: 8px;
font-size: 1em; box-sizing: border-box; }
input:focus, select:focus, textarea:focus {
outline: none; border-color: #6a0dad; }
.btn-submit { width: 100%; padding: 12px; background: #6a0dad;
color: white; border: none; border-radius: 25px;
font-size: 1.1em; cursor: pointer; }
.btn-submit:hover { background: #530a9e; }
.back { display: block; text-align: center; margin-top: 15px;
color: #6a0dad; text-decoration: none; }
.error { color: red; font-size: 0.9em; margin-bottom: 10px; }
</style>
</head>
<body>
<h1>🎹 許願新課程</h1>
<div class="form-box">
@if(errors->any())<ulclass="error">@foreach(errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
<form action="{{ route('gbook.store') }}" method="POST">
@csrf
<label>許願人</label>
<input type="text" name="gbook_poser" value="{{ old('gbook_poser') }}" placeholder="請輸入你的名字">
<label>課程類型</label>
<select name="gbook_kind">
<option value="初級">初級</option>
<option value="中級">中級</option>
<option value="高級">高級</option>
<option value="樂理">樂理</option>
<option value="即興">即興</option>
</select>
<label>課程標題</label>
<input type="text" name="gbook_title" value="{{ old('gbook_title') }}" placeholder="你想學什麼課程?">
<label>許願內容</label>
<textarea name="gbook_msg" rows="5" placeholder="詳細描述你的願望...">{{ old('gbook_msg') }}</textarea>
<button type="submit" class="btn-submit">🎵 送出許願</button>
</form>
<a href="{{ route('gbook.index') }}" class="back">← 回許願板</a>
</div>
</body>
</html>
這是一個 Laravel Blade 的「新增許願」表單頁面,讓使用者輸入姓名、課程類型、課程標題和許願內容,再送到 GbookController@store 儲存到資料庫。
檔案通常是:
resources/views/gbook/create.blade.php
<!DOCTYPE html>
<html lang="zh-Hant-TW">
表示這是一份 HTML5 文件,並指定頁面語言為台灣繁體中文。
<meta charset="UTF-8">
使用 UTF-8 編碼,支援中文、日文和 Emoji。
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
讓頁面能適應手機與平板螢幕。
<title>新增許願</title>
設定瀏覽器分頁標題。
body {
font-family: 'Microsoft JhengHei', sans-serif;
background: #f9f3ff;
}
設定:
h1 {
text-align: center;
color: #6a0dad;
margin-top: 30px;
}
讓標題置中、使用紫色,並與頁面上方保持 30px 間距。
.form-box {
width: 500px;
margin: 30px auto;
background: white;
padding: 30px;
border-radius: 15px;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}
這個區塊包住整個表單。
margin: 30px auto:上下 30px,左右自動置中。在手機上,固定 width: 500px 可能超出畫面,建議改成:
.form-box {
width: 90%;
max-width: 500px;
box-sizing: border-box;
}
這樣在桌面上最大 500px,在手機上則會縮小至適合的寬度。
label {
display: block;
color: #6a0dad;
font-weight: bold;
margin-bottom: 5px;
}
每個表單標籤會:
input[type=text], select, textarea {
width: 100%;
padding: 10px;
margin-bottom: 15px;
border: 2px solid #e0c8ff;
border-radius: 8px;
font-size: 1em;
box-sizing: border-box;
}
同時設定:
各項效果如下:
width: 100%:填滿表單寬度。padding: 10px:增加輸入舒適度。margin-bottom: 15px:欄位之間保留空間。box-sizing: border-box:讓 padding 和邊框包含在設定的寬度內,避免欄位超出容器。input:focus, select:focus, textarea:focus {
outline: none;
border-color: #6a0dad;
}
當使用者正在輸入欄位時:
較重視無障礙時,不建議完全移除 outline,可以改成:
input:focus,
select:focus,
textarea:focus {
outline: 3px solid rgba(106, 13, 173, 0.25);
border-color: #6a0dad;
}
.btn-submit {
width: 100%;
padding: 12px;
background: #6a0dad;
color: white;
border: none;
border-radius: 25px;
font-size: 1.1em;
cursor: pointer;
}
設定送出按鈕:
.btn-submit:hover {
background: #530a9e;
}
滑鼠移到按鈕時,背景變成深紫色。
.back {
display: block;
text-align: center;
margin-top: 15px;
color: #6a0dad;
text-decoration: none;
}
設定「回許願板」連結:
.error {
color: red;
font-size: 0.9em;
margin-bottom: 10px;
}
驗證錯誤會以紅色、較小字體顯示。
<h1>🎹 許願新課程</h1>
<div class="form-box">
h1 是頁面標題。
.form-box 則是白色表單卡片,包住:
@if($errors->any())
<ul class="error">
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
這段是 Laravel Blade 語法。
$errors->any()判斷目前是否有任何驗證錯誤。
Controller 中的驗證是:
$request->validate([
'gbook_poser' => 'required|max:20',
'gbook_kind' => 'required',
'gbook_title' => 'required|max:30',
'gbook_msg' => 'required|max:200',
]);
如果使用者沒有填寫必填欄位,或者超過字數限制,就會產生錯誤。
$errors->all()取得所有錯誤訊息。
@foreach逐筆列出錯誤:
<li>{{ $error }}</li>
最後可能顯示:
The gbook poser field is required.
The gbook title may not be greater than 30 characters.
如果要顯示繁體中文錯誤訊息,可以在:
lang/zh_TW/validation.php
設定語言檔,或在驗證時自訂訊息。
Laravel 會將驗證錯誤與原始輸入資料暫存到 Session,讓重新導向回表單後可以顯示錯誤並保留使用者輸入。 laravel
<form action="{{ route('gbook.store') }}" method="POST">
表示表單送出時:
gbook.store 路由。POST 方法。如果路由設定如下:
Route::post('/gbook', [GbookController::class, 'store'])
->name('gbook.store');
送出後會執行:
GbookController@store
也就是前面介紹的新增資料方法。
@csrf
Laravel 會將它轉換成隱藏欄位,類似:
<input type="hidden"
name="_token"
value="...">
這個 Token 用來確認表單是由自己網站產生,而不是惡意網站偽造的請求。
在 Laravel 的 POST、PUT、PATCH、DELETE 表單中,通常都必須加入:
@csrf
否則可能出現:
419 Page Expired
<label>許願人</label>
<input
type="text"
name="gbook_poser"
value="{{ old('gbook_poser') }}"
placeholder="請輸入你的名字">
name="gbook_poser"這個名稱必須與 Controller 驗證的欄位名稱相同:
'gbook_poser'
送出後,Laravel 才能透過:
$request->gbook_poser
取得資料。
old('gbook_poser')如果驗證失敗,Laravel 會保留使用者上一次輸入的內容。
例如使用者填入:
王小明
但其他欄位驗證失敗,返回表單時:
value="{{ old('gbook_poser') }}"
會自動恢復:
王小明
這樣使用者不必重新輸入。
placeholderplaceholder="請輸入你的名字"
在欄位空白時顯示提示文字。
不過 placeholder 不能完全取代 <label>,目前同時使用 label 和 placeholder 是正確方向。表單控制項應該有清楚的標籤,這對可及性和螢幕閱讀器很重要。 developer.mozilla
<label>課程類型</label>
<select name="gbook_kind">
<option value="初級">初級</option>
<option value="中級">中級</option>
<option value="高級">高級</option>
<option value="樂理">樂理</option>
<option value="即興">即興</option>
</select>
select 建立下拉式選單。
使用者看到的是:
初級
中級
高級
樂理
即興
送出後,Controller 可以取得:
$request->gbook_kind
例如選擇「即興」,送出的值為:
即興
目前第一個選項會預設被選取。如果希望使用者必須主動選擇,可以增加提示選項:
<select name="gbook_kind" required>
<option value="">請選擇課程類型</option>
<option value="初級" @selected(old('gbook_kind') === '初級')>初級</option>
<option value="中級" @selected(old('gbook_kind') === '中級')>中級</option>
<option value="高級" @selected(old('gbook_kind') === '高級')>高級</option>
<option value="樂理" @selected(old('gbook_kind') === '樂理')>樂理</option>
<option value="即興" @selected(old('gbook_kind') === '即興')>即興</option>
</select>
HTML 的 required 可以讓瀏覽器在送出前檢查文字框、下拉選單和文字區域是否有值。 developer.mozilla
<label>課程標題</label>
<input
type="text"
name="gbook_title"
value="{{ old('gbook_title') }}"
placeholder="你想學什麼課程?">
這個欄位對應資料庫:
gbook_title
Controller 驗證限制是:
'required|max:30'
也就是:
<label>許願內容</label>
<textarea
name="gbook_msg"
rows="5"
placeholder="詳細描述你的願望..."
>{{ old('gbook_msg') }}</textarea>
textarea 用來輸入多行文字。
rows="5"設定文字區域大約顯示 5 行高度。
old('gbook_msg')如果驗證失敗,保留使用者原本輸入的內容。
與 input 不同,textarea 的值要放在開始標籤和結束標籤之間:
<textarea name="gbook_msg">{{ old('gbook_msg') }}</textarea>
<button type="submit" class="btn-submit">
🎵 送出許願
</button>
type="submit" 表示按下後送出表單。
送出後的流程是:
POST gbook.store
↓
GbookController@store
↓
驗證資料
↓
Gbook::create()
↓
寫入 gbook 資料表
↓
返回 gbook.index
<a href="{{ route('gbook.index') }}" class="back">
← 回許願板
</a>
利用 Laravel 的命名路由前往:
gbook.index
通常對應:
GbookController@index
最後回到留言清單頁面。
id 與 for目前的寫法:
<label>許願人</label>
<input type="text" name="gbook_poser">
接來來是 美髮業的系統
這組資料適合先插入 users → customers → staff → services → products → appointments → appointment_services → invoices → invoice_items → inventory_logs,因為預約、發票、庫存異動都依賴前面的主資料表
不過有網址覺得有圖有真相
https://laihao.vaserver.com/hairdressing