HackMD
    • Sharing Link copied
    • /edit
    • View mode
      • Edit mode
      • View mode
      • Book mode
      • Slide mode
      Edit mode View mode Book mode Slide mode
    • Note Permission
    • Read
      • Only me
      • Signed-in users
      • Everyone
      Only me Signed-in users Everyone
    • Write
      • Only me
      • Signed-in users
      • Everyone
      Only me Signed-in users Everyone
    • More (Comment, Invitee)
    • Publishing
    • Commenting Enable
      Disabled Forbidden Owners Signed-in users Everyone
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Invitee
    • No invitee
    • Options
    • Versions
    • Transfer ownership
    • Delete this note
    • Template
    • Save as template
    • Insert from template
    • Export
    • Google Drive Export to Google Drive
    • Gist
    • Import
    • Google Drive Import from Google Drive
    • Gist
    • Clipboard
    • Download
    • Markdown
    • HTML
    • Raw HTML
Menu Sharing Help
Menu
Options
Versions Transfer ownership Delete this note
Export
Google Drive Export to Google Drive Gist
Import
Google Drive Import from Google Drive Gist Clipboard
Download
Markdown HTML Raw HTML
Back
Sharing
Sharing Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
More (Comment, Invitee)
Publishing
More (Comment, Invitee)
Commenting Enable
Disabled Forbidden Owners Signed-in users Everyone
Permission
Owners
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Invitee
No invitee
   owned this note    owned this note      
Published Linked with
Like BookmarkBookmarked
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
以下範例是使用 Laravel 8/9/10 皆可通用的示範程式碼,示範如何建立一個包含「會員系統」與「討論區」功能的網路討論區專案。程式碼側重在 關鍵功能與流程 的展示,實際專案可再根據需求做更多細節優化。整個回答將包含: 1. 資料庫設計(Migrations) 2. Model (Eloquent) 設計 3. 中介層 (Middleware) 設計 4. 路由 (Routes) 5. Controller 與部分 Request 驗證 6. Blade 模板 (前端) 7. 程式碼與功能說明 1. 資料庫設計(Migrations) 1.1 users 資料表 此處包含會員基本資料,如帳號(email)、顯示名稱(name)、個人頭像(avatar)、角色(role)等。 use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateUsersTable extends Migration { public function up() { Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); // 使用者名稱 $table->string('email')->unique(); // 使用者 Email (唯一) $table->string('password'); // 使用者密碼 $table->string('avatar')->nullable(); // 頭像路徑 (可選) $table->string('role')->default('member'); // 角色 (可為 'admin', 'moderator', 'member' 等) $table->text('bio')->nullable(); // 自我介紹 $table->rememberToken(); $table->timestamps(); }); } public function down() { Schema::dropIfExists('users'); } } 1.2 forums 資料表 此處放置討論區(板塊)的資訊。 use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateForumsTable extends Migration { public function up() { Schema::create('forums', function (Blueprint $table) { $table->id(); $table->string('name'); // 討論區名稱 $table->text('description'); // 討論區描述 $table->timestamps(); }); } public function down() { Schema::dropIfExists('forums'); } } 1.3 posts 資料表 用來儲存文章資訊,並跟所屬討論區和發文者做關聯。 use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreatePostsTable extends Migration { public function up() { Schema::create('posts', function (Blueprint $table) { $table->id(); $table->string('title'); // 文章標題 $table->text('content'); // 文章內容 $table->unsignedBigInteger('forum_id'); // 所屬討論區 $table->unsignedBigInteger('user_id'); // 發文者 (會員) $table->string('image_path')->nullable(); // 文章上傳圖片的路徑 (可選) $table->timestamps(); // 外鍵關聯 $table->foreign('forum_id') ->references('id') ->on('forums') ->onDelete('cascade'); $table->foreign('user_id') ->references('id') ->on('users') ->onDelete('cascade'); }); } public function down() { Schema::dropIfExists('posts'); } } 2. Model (Eloquent) 設計 2.1 User Model namespace App\Models; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; class User extends Authenticatable { use HasFactory, Notifiable; protected $fillable = [ 'name', 'email', 'password', 'avatar', 'role', 'bio' ]; protected $hidden = [ 'password', 'remember_token', ]; // 一位使用者可以發多篇文章 (一對多) public function posts() { return $this->hasMany(Post::class); } } 2.2 Forum Model namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Forum extends Model { use HasFactory; protected $fillable = [ 'name', 'description' ]; // 一個討論區可以有多篇文章 (一對多) public function posts() { return $this->hasMany(Post::class); } } 2.3 Post Model namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Post extends Model { use HasFactory; protected $fillable = [ 'title', 'content', 'forum_id', 'user_id', 'image_path' ]; // 一篇文章屬於一個討論區 (多對一) public function forum() { return $this->belongsTo(Forum::class); } // 一篇文章由一個使用者發文 (多對一) public function user() { return $this->belongsTo(User::class); } } 3. 中介層 (Middleware) 設計 3.1 角色檢查範例:CheckRole Middleware 假設我們需要判斷使用者是否為「網站管理員」或「討論區管理員」,可在 app/Http/Middleware/CheckRole.php 中設定邏輯: namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class CheckRole { /** * Handle an incoming request. */ public function handle(Request $request, Closure $next, ...$roles) { $user = Auth::user(); if (!$user) { // 尚未登入 return redirect()->route('login')->with('error', '請先登入'); } // 檢查使用者的角色是否在允許清單中 if (!in_array($user->role, $roles)) { return redirect()->route('home')->with('error', '您沒有存取此頁面的權限'); } return $next($request); } } 在 kernel.php 中註冊: 使用方式(範例): Route::group(['middleware' => ['auth', 'checkRole:admin,moderator']], function() { // 只有 admin 或 moderator 可以進入的路由 }); 4. 路由 (Routes) 假設在 routes/web.php,設置以下基本路由: use App\Http\Controllers\AuthController; use App\Http\Controllers\UserController; use App\Http\Controllers\ForumController; use App\Http\Controllers\PostController; // 首頁路由 Route::get('/', function () { return view('welcome'); })->name('home'); // 會員相關 (登入、登出、註冊、修改資料) Route::get('/register', [AuthController::class, 'showRegistrationForm'])->name('register.show'); Route::post('/register', [AuthController::class, 'register'])->name('register'); Route::get('/login', [AuthController::class, 'showLoginForm'])->name('login.show'); Route::post('/login', [AuthController::class, 'login'])->name('login'); Route::post('/logout', [AuthController::class, 'logout'])->name('logout'); Route::middleware('auth')->group(function() { // 會員資料修改 Route::get('/user/profile', [UserController::class, 'edit'])->name('user.profile'); Route::post('/user/profile', [UserController::class, 'update'])->name('user.update'); }); // 討論區列表 & 文章列表 Route::get('/forums', [ForumController::class, 'index'])->name('forums.index'); Route::get('/forums/{forum}', [ForumController::class, 'show'])->name('forums.show'); // 文章相關 Route::middleware('auth')->group(function() { Route::get('/posts/create', [PostController::class, 'create'])->name('posts.create'); Route::post('/posts', [PostController::class, 'store'])->name('posts.store'); Route::get('/posts/{post}/edit', [PostController::class, 'edit'])->name('posts.edit'); Route::put('/posts/{post}', [PostController::class, 'update'])->name('posts.update'); }); 5. Controller 與 Request 驗證 5.1 AuthController (會員註冊與登入) namespace App\Http\Controllers; use App\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Illuminate\Validation\Rules; class AuthController extends Controller { // 顯示註冊表單 public function showRegistrationForm() { return view('auth.register'); } // 處理註冊邏輯 public function register(Request $request) { // 表單驗證 $request->validate([ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 'password' => ['required', 'confirmed', Rules\Password::defaults()], ]); // 建立使用者 $user = User::create([ 'name' => $request->name, 'email' => $request->email, 'password' => Hash::make($request->password), ]); // 自動登入 Auth::login($user); return redirect()->route('home')->with('success', '註冊成功,您已登入!'); } // 顯示登入表單 public function showLoginForm() { return view('auth.login'); } // 處理登入邏輯 public function login(Request $request) { // 表單驗證 $credentials = $request->validate([ 'email' => ['required', 'email'], 'password' => ['required'], ]); // 嘗試登入 if (Auth::attempt($credentials, $request->remember)) { $request->session()->regenerate(); return redirect()->route('home')->with('success', '登入成功'); } return back()->withErrors([ 'email' => '帳號或密碼錯誤', ]); } // 登出 public function logout(Request $request) { Auth::logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect()->route('home')->with('success', '您已登出'); } } 5.2 UserController (會員資料修改) namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; class UserController extends Controller { public function edit() { $user = Auth::user(); return view('user.edit', compact('user')); } public function update(Request $request) { $user = Auth::user(); // 簡易驗證 $request->validate([ 'name' => 'required|string|max:255', 'password' => 'nullable|confirmed|min:8', 'avatar' => 'nullable|image|max:2048', 'bio' => 'nullable|string' ]); $user->name = $request->name; // 若有修改密碼 if ($request->filled('password')) { $user->password = Hash::make($request->password); } // 處理頭像 (avatar) 上傳 if ($request->hasFile('avatar')) { // 存到 storage/app/public/avatars $path = $request->file('avatar')->store('public/avatars'); // 可以自行處理檔案名稱、路徑 $user->avatar = $path; } $user->bio = $request->bio; $user->save(); return redirect()->back()->with('success', '會員資料已更新'); } } 5.3 ForumController (討論區列表、單一討論區顯示) namespace App\Http\Controllers; use App\Models\Forum; use Illuminate\Http\Request; class ForumController extends Controller { // 討論區總列表 public function index() { $forums = Forum::all(); return view('forums.index', compact('forums')); } // 顯示單一討論區以及其文章列表(分頁) public function show(Forum $forum) { // 每頁顯示 20 篇文章 $posts = $forum->posts()->paginate(20); return view('forums.show', compact('forum', 'posts')); } } 5.4 PostController (文章新增、編輯) namespace App\Http\Controllers; use App\Models\Post; use App\Models\Forum; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class PostController extends Controller { // 顯示新增文章表單 public function create() { $forums = Forum::all(); // 用來在前端選擇要發在哪個討論區 return view('posts.create', compact('forums')); } // 新增文章 public function store(Request $request) { // 驗證 $request->validate([ 'title' => 'required|string|max:255', 'content' => 'required|string', 'forum_id' => 'required|exists:forums,id', 'image' => 'nullable|image|max:2048' ]); $post = new Post(); $post->title = $request->title; $post->content = $request->content; $post->forum_id = $request->forum_id; $post->user_id = Auth::id(); // 處理圖片上傳 if ($request->hasFile('image')) { // 這裡示範存到本機 storage 路徑 $path = $request->file('image')->store('public/posts'); $post->image_path = $path; } $post->save(); return redirect()->route('forums.show', $post->forum_id) ->with('success', '文章發表成功'); } // 顯示編輯文章表單 public function edit(Post $post) { // 只有文章作者或管理者可以編輯 (自行在此檢查) $this->authorize('update', $post); // 也可用 Policy $forums = Forum::all(); return view('posts.edit', compact('post', 'forums')); } // 更新文章 public function update(Request $request, Post $post) { // 只有文章作者或管理者可以編輯 (自行在此檢查) $this->authorize('update', $post); // 驗證 $request->validate([ 'title' => 'required|string|max:255', 'content' => 'required|string', 'forum_id' => 'required|exists:forums,id', 'image' => 'nullable|image|max:2048' ]); $post->title = $request->title; $post->content = $request->content; $post->forum_id = $request->forum_id; // 處理圖片上傳 if ($request->hasFile('image')) { $path = $request->file('image')->store('public/posts'); $post->image_path = $path; } $post->save(); return redirect()->route('forums.show', $post->forum_id) ->with('success', '文章更新成功'); } } 6. Blade 模板 (前端) 下列僅示範主要 Blade 檔案的結構與表單,實際專案可根據需求加上 CSS、JS、Layout 等。 6.1 resources/views/auth/register.blade.php (註冊) @extends('layouts.app') @section('content') <h2>會員註冊</h2> <form action="{{ route('register') }}" method="POST"> @csrf <div> <label for="name">名稱:</label> <input type="text" name="name" value="{{ old('name') }}" required> @error('name') <div>{{ $message }}</div> @enderror </div> <div> <label for="email">Email:</label> <input type="email" name="email" value="{{ old('email') }}" required> @error('email') <div>{{ $message }}</div> @enderror </div> <div> <label for="password">密碼:</label> <input type="password" name="password" required> @error('password') <div>{{ $message }}</div> @enderror </div> <div> <label for="password_confirmation">確認密碼:</label> <input type="password" name="password_confirmation" required> </div> <button type="submit">註冊</button> </form> @endsection 6.2 resources/views/auth/login.blade.php (登入) @extends('layouts.app') @section('content') <h2>會員登入</h2> <form action="{{ route('login') }}" method="POST"> @csrf <div> <label for="email">Email:</label> <input type="email" name="email" value="{{ old('email') }}" required> @error('email') <div>{{ $message }}</div> @enderror </div> <div> <label for="password">密碼:</label> <input type="password" name="password" required> </div> <div> <label for="remember">記住我</label> <input type="checkbox" name="remember"> </div> <button type="submit">登入</button> </form> @endsection 6.3 resources/views/posts/create.blade.php (文章新增) @extends('layouts.app') @section('content') <h2>發表新文章</h2> <form action="{{ route('posts.store') }}" method="POST" enctype="multipart/form-data"> @csrf <div> <label for="title">標題:</label> <input type="text" name="title" value="{{ old('title') }}" required> @error('title') <div>{{ $message }}</div> @enderror </div> <div> <label for="content">內容:</label> <textarea name="content" rows="5" required>{{ old('content') }}</textarea> @error('content') <div>{{ $message }}</div> @enderror </div> <div> <label for="forum_id">討論區:</label> <select name="forum_id" required> <option value="">--請選擇--</option> @foreach($forums as $forum) <option value="{{ $forum->id }}" {{ old('forum_id') == $forum->id ? 'selected' : '' }}> {{ $forum->name }} </option> @endforeach </select> @error('forum_id') <div>{{ $message }}</div> @enderror </div> <div> <label for="image">圖片上傳:</label> <input type="file" name="image" accept="image/*"> @error('image') <div>{{ $message }}</div> @enderror </div> <button type="submit">發表文章</button> </form> @endsection 6.4 resources/views/layouts/app.blade.php (範例主版型) <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Laravel Forum</title> </head> <body> <header> <nav> <a href="{{ route('home') }}">首頁</a> <a href="{{ route('forums.index') }}">討論區列表</a> @guest <a href="{{ route('login.show') }}">登入</a> <a href="{{ route('register.show') }}">註冊</a> @else <form action="{{ route('logout') }}" method="POST" style="display:inline;"> @csrf <button type="submit">登出</button> </form> @endguest </nav> </header> <main> @if(session('success')) <div style="color: green;">{{ session('success') }}</div> @endif @if(session('error')) <div style="color: red;">{{ session('error') }}</div> @endif @yield('content') </main> </body> </html> 7. 程式碼與功能說明 1. 資料庫遷移 (Migrations) • users:儲存會員資訊,包括名稱、email、密碼、頭像路徑、角色、簡介等。 • forums:討論區(板塊)資訊,如名稱和描述。 • posts:文章資訊,包括標題、內容、發文者 ID、對應討論區 ID、圖片路徑等。 2. Eloquent 關聯 • User 與 Post 是一對多 (One to Many):User 可以擁有多個 posts()。 • Forum 與 Post 也是一對多 (One to Many):Forum 可以有多個 posts()。 • Post 分別屬於 User 和 Forum (多對一):$post->user()、$post->forum()。 3. Middleware • 建立了 CheckRole 用於檢查使用者角色,若不符合要求則導回首頁。 • 可在路由或控制器中使用 checkRole:admin,moderator 等。 • 或者使用 Laravel 的 授權策略 (Policies) 做更細緻的權限控管。 4. 會員註冊與登入 • AuthController::register 先驗證表單,接著建立 User,最後自動登入。 • AuthController::login 使用 Auth::attempt 嘗試驗證並登入。 • AuthController::logout 執行 Auth::logout 並重設 session token。 5. 會員資料修改 (UserController) • 在 edit() 取得目前登入者資訊,並返回編輯表單。 • 在 update() 做表單驗證後,更新使用者名稱、密碼、頭像、簡介等欄位。 • 頭像可透過 $request->file('avatar')->store('public/avatars') 進行本機儲存。 6. 討論區功能 (ForumController) • index():顯示所有 Forum。 • show():顯示單一討論區內文,並以 paginate(20) 顯示該討論區的文章列表。 7. 文章功能 (PostController) • create():顯示新增文章表單,並讓使用者選擇所屬的討論區。 • store():驗證表單後,建立 Post,並可上傳圖片(儲存到 storage/app/public/posts)。 • edit():顯示編輯文章表單。 • update():更新文章標題、內容、所屬討論區,以及圖片檔案等。 總結 以上範例提供了 Laravel 中實作會員系統與討論區核心功能的邏輯,包括: • 會員註冊/登入/登出 • 會員角色與權限檢查 (Middleware) • 文章新增、編輯、上傳圖片 • 討論區板塊列表與文章分頁 對照需求,包含了: 1. 使用 Blade 模板構建頁面。 2. 註冊、登入頁面有基礎驗證(Email 格式、密碼長度/確認)。 3. 文章編輯支援文字輸入、圖片上傳,以及在 Blade 中可以加入簡單的文字樣式(可自行整合 WYSIWYG 編輯器)。 4. 後端會員功能包括註冊、登入、會員資料修改、中介層(Middleware)權限檢查與 API(可把 update 改為 API)。 5. 討論區功能:分類(Forums)、文章列表20篇分頁(Posts)、支援圖片上傳。 6. 完整遷移檔(Migrations)、Eloquent Model 關聯說明(一對多關係)。 此專案僅是最基礎的範例,可進一步整合更多功能(例如:留言功能、通知、站內信、SEO 設計、文章搜尋、投票、編輯器套件等),也可將圖片上傳改用第三方儲存(如 S3、阿里雲 OSS、Google Cloud Storage),只需調整 filesystems.php 以及上傳邏輯即可。 希望能幫助您快速了解並上手 Laravel 如何實作完整的討論區與會員管理流程。祝專案開發順利!

Import from clipboard

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lost their connection.

Create a note from template

Create a note from template

Oops...
This template has been removed or transferred.


Upgrade

All
  • All
  • Team
No template.

Create a template


Upgrade

Delete template

Do you really want to delete this template?

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Forgot password

or

Sign in via GitHub

New to HackMD? Sign up

Help

  • English
  • 中文
  • 日本語

Documents

Tutorials

Book Mode Tutorial

Slide Example

YAML Metadata

Resources

Releases

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions

Versions

Upgrade now

Version named by    

More Less
  • Edit
  • Delete

Note content is identical to the latest version.
Compare with
    Choose a version
    No search result
    Version not found

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.