https://laihao.vaserver.com/hairdressingusers
要來講解美髮預約系統_users的程式碼
就是MVC架構
各畫面的程式碼解說
新增的前端畫面程式碼
/home/laihao/public_html/resources/views/hairdressing/users/create.blade.php
新增的前端畫面程式碼
<!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 { width: 90%; max-width: 500px; margin: 0 auto; background: white;
padding: 25px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
label { display: block; margin-top: 15px; margin-bottom: 5px; color: #555; font-weight: bold; }
input, select { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 6px;
box-sizing: border-box; font-family: inherit; }
.btn { display: block; width: 100%; margin-top: 20px; background: #6a0dad; color: white;
text-align: center; padding: 10px; border-radius: 25px; text-decoration: none;
border: none; cursor: pointer; font-size: 15px; }
.btn:hover { background: #530a9e; }
.back { display: block; text-align: center; margin-top: 15px; color: #6a0dad; }
.error { color: #d9534f; font-size: 13px; margin-top: 4px; }
</style>
</head>
<body>
<h1>✨ 新增使用者</h1>
<form action="{{ route('hairdressingusers.store') }}" method="POST">
@csrf
<label>姓名</label>
<input type="text" name="name" value="{{ old('name') }}" required>
@error('name') <div class="error">{{ $message }}</div> @enderror
<label>Email</label>
<input type="email" name="email" value="{{ old('email') }}" required>
@error('email') <div class="error">{{ $message }}</div> @enderror
<label>密碼</label>
<input type="password" name="password" required>
@error('password') <div class="error">{{ $message }}</div> @enderror
<label>角色</label>
<select name="role" required>
<option value="admin" {{ old('role') == 'admin' ? 'selected' : '' }}>管理員</option>
<option value="receptionist" {{ old('role') == 'receptionist' ? 'selected' : '' }}>櫃台</option>
<option value="stylist" {{ old('role') == 'stylist' ? 'selected' : '' }}>設計師</option>
</select>
@error('role') <div class="error">{{ $message }}</div> @enderror
<label>狀態</label>
<select name="status" required>
<option value="active" {{ old('status') == 'active' ? 'selected' : '' }}>啟用</option>
<option value="inactive" {{ old('status') == 'inactive' ? 'selected' : '' }}>停用</option>
</select>
@error('status') <div class="error">{{ $message }}</div> @enderror
<button type="submit" class="btn">儲存使用者</button>
</form>
<a href="{{ route('hairdressingusers.index') }}" class="back">← 返回使用者列表</a>
</body>
</html>
這是一個 Laravel Blade「新增使用者」頁面。它建立一個表單,讓管理者填寫姓名、Email、密碼、角色與狀態;送出後會呼叫 hairdressingusers.store 路由,由控制器驗證並寫入資料庫。
<!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>
<!DOCTYPE html>:宣告此頁面採用 HTML5。lang="zh-Hant-TW":告訴瀏覽器、搜尋引擎與輔助工具,頁面語言是台灣繁體中文。charset="UTF-8":確保中文、emoji(例如 ✨)能正確顯示。viewport:讓手機版畫面依裝置寬度縮放,提升 RWD 顯示效果。<title>:瀏覽器分頁顯示「新增使用者」。body {
font-family: 'Microsoft JhengHei', sans-serif;
background: #f9f3ff;
}
background: #f9f3ff 設定淡紫色背景。form {
width: 90%;
max-width: 500px;
margin: 0 auto;
background: white;
padding: 25px;
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}
這段讓表單呈現置中的白色卡片:
width: 90%:在小螢幕保留左右邊距。max-width: 500px:桌機不會無限拉寬。margin: 0 auto:水平置中。padding、border-radius、box-shadow:增加內距、圓角與陰影,形成卡片風格。input, select {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 6px;
box-sizing: border-box;
font-family: inherit;
}
input, select:統一文字輸入框與下拉選單的外觀。width: 100%:欄位填滿表單寬度。box-sizing: border-box:讓 padding 和 border 都算在 100% 寬度內,避免欄位超出表單。font-family: inherit:輸入欄位沿用頁面字體。.btn { ... }
.btn:hover { background: #530a9e; }
.btn:送出按鈕為紫色、白字、全寬、圓角。.btn:hover:滑鼠移到按鈕上時顏色變深,提供互動回饋。.error {
color: #d9534f;
font-size: 13px;
margin-top: 4px;
}
.error:欄位驗證失敗時顯示紅色錯誤訊息。<form action="{{ route('hairdressingusers.store') }}" method="POST">
@csrf
action="{{ route('hairdressingusers.store') }}":利用 Laravel 的命名路由產生表單送出網址;該路由通常對應控制器的 store() 方法。method="POST":使用 POST 請求新增資料。@csrf:Laravel Blade 指令,產生 CSRF Token 隱藏欄位,防止跨站請求偽造攻擊。缺少它時,Laravel 通常會回傳 419 Page Expired。對應路由通常類似:
Route::resource('hairdressingusers', HairdressingUserController::class);
其中的 hairdressingusers.store 會對應:
POST /hairdressingusers
並執行控制器中的:
public function store(Request $request)
<label>姓名</label>
<input type="text" name="name" value="{{ old('name') }}" required>
@error('name') <div class="error">{{ $message }}</div> @enderror
name="name":送到控制器後可用 $request->name 或 $request->input('name') 取得。required:瀏覽器端要求必填,但後端仍必須保留 Laravel 的驗證規則。old('name'):若後端驗證失敗並導回上一頁,保留使用者原先輸入的姓名。@error('name'):如果 name 驗證失敗,顯示控制器驗證回傳的錯誤訊息。<label>Email</label>
<input type="email" name="email" value="{{ old('email') }}" required>
@error('email') <div class="error">{{ $message }}</div> @enderror
type="email":瀏覽器會先進行基本 email 格式檢查。name="email":對應控制器中的 email 驗證規則,例如 required|email|max:150|unique:...。old('email'):驗證失敗後保留原本輸入的 Email。<label>密碼</label>
<input type="password" name="password" required>
@error('password') <div class="error">{{ $message }}</div> @enderror
type="password":輸入字元在畫面上會被遮蔽。old('password'),這是正確且較安全的做法;驗證失敗後不應把密碼重新帶回頁面。Hash::make($request->password) 再寫入資料庫,而不是直接儲存使用者輸入的明文密碼。<select name="role" required>
<option value="admin" {{ old('role') == 'admin' ? 'selected' : '' }}>管理員</option>
<option value="receptionist" {{ old('role') == 'receptionist' ? 'selected' : '' }}>櫃台</option>
<option value="stylist" {{ old('role') == 'stylist' ? 'selected' : '' }}>設計師</option>
</select>
name="role":送出 admin、receptionist 或 stylist 其中一個英文值。old('role') == 'admin' ? 'selected' : ''
代表若前一次選的是 admin,驗證失敗回到表單時就自動選回「管理員」。'role' => 'required|in:admin,receptionist,stylist',
<select name="status" required>
<option value="active" {{ old('status') == 'active' ? 'selected' : '' }}>啟用</option>
<option value="inactive" {{ old('status') == 'inactive' ? 'selected' : '' }}>停用</option>
</select>
active:帳號可正常使用。inactive:帳號被停用。old('status'),在驗證失敗後保留選擇結果。'status' => 'required|in:active,inactive',
<button type="submit" class="btn">儲存使用者</button>
type="submit":按下後送出整個表單。hairdressingusers.store 路由。<a href="{{ route('hairdressingusers.index') }}" class="back">
← 返回使用者列表
</a>
hairdressingusers.store。HairdressingUserController::store() 進行欄位驗證。@error 顯示錯誤,old() 保留非敏感輸入內容。編輯的前端畫面程式碼
/home/laihao/public_html/resources/views/hairdressing/users/edit.blade.php
程式碼
<!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 { width: 90%; max-width: 500px; margin: 0 auto; background: white;
padding: 25px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
label { display: block; margin-top: 15px; margin-bottom: 5px; color: #555; font-weight: bold; }
input, select { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 6px;
box-sizing: border-box; font-family: inherit; }
.hint { font-size: 12px; color: #999; margin-top: 4px; }
.btn { display: block; width: 100%; margin-top: 20px; background: #6a0dad; color: white;
text-align: center; padding: 10px; border-radius: 25px; text-decoration: none;
border: none; cursor: pointer; font-size: 15px; }
.btn:hover { background: #530a9e; }
.back { display: block; text-align: center; margin-top: 15px; color: #6a0dad; }
.error { color: #d9534f; font-size: 13px; margin-top: 4px; }
</style>
</head>
<body>
<h1>✏️ 編輯使用者</h1>
<form action="{{ route('hairdressingusers.update', $hairdressinguser->id) }}" method="POST">
@csrf
@method('PUT')
<label>姓名</label>
<input type="text" name="name" value="{{ old('name', $hairdressinguser->name) }}" required>
@error('name') <div class="error">{{ $message }}</div> @enderror
<label>Email</label>
<input type="email" name="email" value="{{ old('email', $hairdressinguser->email) }}" required>
@error('email') <div class="error">{{ $message }}</div> @enderror
<label>密碼</label>
<input type="password" name="password">
<div class="hint">留空表示不修改密碼</div>
@error('password') <div class="error">{{ $message }}</div> @enderror
<label>角色</label>
<select name="role" required>
<option value="admin" {{ old('role', $hairdressinguser->role) == 'admin' ? 'selected' : '' }}>管理員</option>
<option value="receptionist" {{ old('role', $hairdressinguser->role) == 'receptionist' ? 'selected' : '' }}>櫃台</option>
<option value="stylist" {{ old('role', $hairdressinguser->role) == 'stylist' ? 'selected' : '' }}>設計師</option>
</select>
@error('role') <div class="error">{{ $message }}</div> @enderror
<label>狀態</label>
<select name="status" required>
<option value="active" {{ old('status', $hairdressinguser->status) == 'active' ? 'selected' : '' }}>啟用</option>
<option value="inactive" {{ old('status', $hairdressinguser->status) == 'inactive' ? 'selected' : '' }}>停用</option>
</select>
@error('status') <div class="error">{{ $message }}</div> @enderror
<button type="submit" class="btn">更新使用者</button>
</form>
<a href="{{ route('hairdressingusers.index') }}" class="back">← 返回使用者列表</a>
</body>
</html>
路由明天來寫~然後預計開始另一個網頁的解說