Laravel 11: สร้างแอปพลิเคชันสมบูรณ์ตั้งแต่เริ่มต้น
คู่มือครบวงจรสำหรับสร้างแอปพลิเคชัน Laravel 11 พร้อมระบบยืนยันตัวตน, REST API, Eloquent ORM และการ Deploy บทเรียนเชิงปฏิบัติสำหรับนักพัฒนาระดับเริ่มต้นถึงกลาง

Laravel 11 ปฏิวัติการพัฒนา PHP สมัยใหม่ด้วยสถาปัตยกรรมที่กระชับและประสิทธิภาพที่ได้รับการปรับแต่ง เวอร์ชันหลักนี้ลบไฟล์คอนฟิกค่าเริ่มต้นจำนวนมาก นำเสนอโครงสร้างที่เรียบง่ายขึ้น และปรับปรุงประสบการณ์นักพัฒนาอย่างมีนัยสำคัญ คู่มือนี้จะพาผ่านกระบวนการสร้างแอปพลิเคชันจัดการงานอย่างครบถ้วน ตั้งแต่การติดตั้งจนถึงการ Deploy
Laravel 11 ใช้โครงสร้างแบบ Minimalist: ไม่มีไฟล์ Kernel อีกต่อไป คอนฟิกรวมศูนย์ใน bootstrap/app.php และไดเรกทอรี app/ ที่สะอาดขึ้น เฟรมเวิร์กต้องการ PHP 8.2 ขั้นต่ำ และรองรับ SQLite แบบ Native สำหรับการเริ่มต้นอย่างรวดเร็ว
การติดตั้งและตั้งค่าโปรเจกต์
Laravel 11 ติดตั้งผ่าน Composer หรือ Laravel installer โครงสร้างโปรเจกต์ใหม่กระชับกว่าเดิม มีไฟล์คอนฟิกที่ต้องจัดการน้อยลงตั้งแต่เริ่มต้น
# terminal
# Install the Laravel installer (recommended)
composer global require laravel/installer
# Create a new Laravel 11 project
laravel new task-manager
# Or directly with Composer
composer create-project laravel/laravel task-manager
# Navigate to the project
cd task-managerInstaller มีตัวเลือกแบบโต้ตอบหลายอย่าง: เลือก Starter Kit (Breeze, Jetstream) เฟรมเวิร์กทดสอบ (Pest, PHPUnit) และฐานข้อมูล
# terminal
# Start the development server
php artisan serve
# Server starts at http://localhost:8000การตั้งค่าฐานข้อมูล
Laravel 11 ใช้ SQLite เป็นค่าเริ่มต้น เหมาะสำหรับการพัฒนา สำหรับแอปพลิเคชัน Production การตั้งค่า MySQL หรือ PostgreSQL ทำในไฟล์ .env
# .env
# MySQL configuration
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=task_manager
DB_USERNAME=root
DB_PASSWORD=secret
# PostgreSQL configuration (alternative)
# DB_CONNECTION=pgsql
# DB_HOST=127.0.0.1
# DB_PORT=5432
# DB_DATABASE=task_manager
# DB_USERNAME=postgres
# DB_PASSWORD=secretตรวจสอบการเชื่อมต่อฐานข้อมูลด้วยคำสั่ง Artisan
# terminal
# Verify database connection
php artisan db:show
# Run default migrations
php artisan migrateการสร้าง Model และ Migration
Eloquent ORM ทำให้การจัดการข้อมูลง่ายขึ้นด้วย Model ที่มีความหมายชัดเจน คำสั่ง make:model สร้าง Model, Migration, Controller และ Factory ในคราวเดียว
# terminal
# Generate Task model with migration, factory, seeder, and controller
php artisan make:model Task -mfsc
# -m : migration
# -f : factory
# -s : seeder
# -c : controllerคำสั่งนี้สร้างไฟล์สำคัญสี่ไฟล์สำหรับการจัดการงานอย่างครบถ้วน
<?php
// database/migrations/2026_01_14_000000_create_tasks_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
// Migration to create the tasks table
return new class extends Migration
{
public function up(): void
{
Schema::create('tasks', function (Blueprint $table) {
// Auto-incrementing primary key
$table->id();
// Relationship with the owner user
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
// Task title (required)
$table->string('title');
// Detailed description (optional)
$table->text('description')->nullable();
// Status: pending, in_progress, completed
$table->string('status')->default('pending');
// Priority: low, medium, high
$table->string('priority')->default('medium');
// Due date (optional)
$table->date('due_date')->nullable();
// Completion marker
$table->timestamp('completed_at')->nullable();
// Automatic timestamps (created_at, updated_at)
$table->timestamps();
// Soft deletes for trash functionality
$table->softDeletes();
// Indexes to optimize frequent queries
$table->index(['user_id', 'status']);
$table->index('due_date');
});
}
public function down(): void
{
Schema::dropIfExists('tasks');
}
};Migration กำหนดโครงสร้างตารางพร้อมความสัมพันธ์ ดัชนี และ Soft Delete เพื่อป้องกันการสูญเสียข้อมูลโดยไม่ตั้งใจ
<?php
// app/Models/Task.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Builder;
class Task extends Model
{
// Traits for advanced functionality
use HasFactory, SoftDeletes;
// Mass-assignable attributes
protected $fillable = [
'user_id',
'title',
'description',
'status',
'priority',
'due_date',
'completed_at',
];
// Automatic attribute casting
protected function casts(): array
{
return [
'due_date' => 'date',
'completed_at' => 'datetime',
];
}
// Constants for valid statuses
public const STATUS_PENDING = 'pending';
public const STATUS_IN_PROGRESS = 'in_progress';
public const STATUS_COMPLETED = 'completed';
// Constants for priorities
public const PRIORITY_LOW = 'low';
public const PRIORITY_MEDIUM = 'medium';
public const PRIORITY_HIGH = 'high';
// Relationship: a task belongs to a user
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
// Scope: pending tasks
public function scopePending(Builder $query): Builder
{
return $query->where('status', self::STATUS_PENDING);
}
// Scope: in-progress tasks
public function scopeInProgress(Builder $query): Builder
{
return $query->where('status', self::STATUS_IN_PROGRESS);
}
// Scope: completed tasks
public function scopeCompleted(Builder $query): Builder
{
return $query->where('status', self::STATUS_COMPLETED);
}
// Scope: overdue tasks
public function scopeOverdue(Builder $query): Builder
{
return $query->where('due_date', '<', now())
->whereNull('completed_at');
}
// Scope: tasks for a specific user
public function scopeForUser(Builder $query, int $userId): Builder
{
return $query->where('user_id', $userId);
}
// Accessor: check if task is overdue
public function getIsOverdueAttribute(): bool
{
return $this->due_date
&& $this->due_date->isPast()
&& !$this->completed_at;
}
// Method: mark as completed
public function markAsCompleted(): void
{
$this->update([
'status' => self::STATUS_COMPLETED,
'completed_at' => now(),
]);
}
}Model Task ใช้ Eloquent Scope สำหรับ Query ที่อ่านง่ายและนำกลับมาใช้ซ้ำได้ ค่าคงที่รวมศูนย์ค่าที่ถูกต้องสำหรับสถานะและลำดับความสำคัญ
Trait SoftDeletes เพิ่มคอลัมน์ deleted_at งานที่ถูกลบจะไม่หายไปจากฐานข้อมูล แต่จะถูกทำเครื่องหมายว่าถูกลบแล้ว ใช้ withTrashed() เพื่อรวมข้อมูลเหล่านี้ในการ Query
การตั้งค่าระบบยืนยันตัวตนด้วย Breeze
Laravel Breeze มีระบบยืนยันตัวตนครบถ้วนพร้อม View แบบ Blade หรือ API การติดตั้งใช้เวลาเพียงไม่กี่นาทีและสร้างทุกสิ่งที่จำเป็น: Route, Controller, View และ Test
# terminal
# Install Laravel Breeze
composer require laravel/breeze --dev
# Install the Blade stack (traditional)
php artisan breeze:install blade
# Or for API only (SPA/mobile)
php artisan breeze:install api
# Compile assets
npm install && npm run build
# Run migrations (users, sessions tables, etc.)
php artisan migrateBreeze สร้าง Route ยืนยันตัวตน Controller และ View สำหรับการลงทะเบียน เข้าสู่ระบบ รีเซ็ตรหัสผ่าน และยืนยันอีเมล
<?php
// app/Models/User.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use HasFactory, Notifiable;
protected $fillable = [
'name',
'email',
'password',
];
protected $hidden = [
'password',
'remember_token',
];
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
// Relationship: a user owns multiple tasks
public function tasks(): HasMany
{
return $this->hasMany(Task::class);
}
// Shortcut: user's pending tasks
public function pendingTasks(): HasMany
{
return $this->tasks()->pending();
}
// Shortcut: user's overdue tasks
public function overdueTasks(): HasMany
{
return $this->tasks()->overdue();
}
}พร้อมที่จะพิชิตการสัมภาษณ์ Laravel แล้วหรือยังครับ?
ฝึกฝนด้วยตัวจำลองแบบโต้ตอบ, flashcards และแบบทดสอบเทคนิคครับ
การสร้าง Controller และ Route
Controller จัดการ Logic ทางธุรกิจระหว่าง HTTP Request และ Model Laravel 11 สนับสนุนการใช้ Single-action Controller หรือ RESTful Resource
<?php
// app/Http/Controllers/TaskController.php
namespace App\Http\Controllers;
use App\Models\Task;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;
use Illuminate\Support\Facades\Gate;
class TaskController extends Controller
{
// List tasks for the authenticated user
public function index(Request $request): View
{
// Retrieve tasks with optional filtering
$tasks = $request->user()
->tasks()
->when($request->status, fn($q, $status) => $q->where('status', $status))
->when($request->priority, fn($q, $priority) => $q->where('priority', $priority))
->orderBy('due_date')
->orderBy('priority', 'desc')
->paginate(15);
return view('tasks.index', compact('tasks'));
}
// Creation form
public function create(): View
{
return view('tasks.create');
}
// Store a new task
public function store(Request $request): RedirectResponse
{
// Validate incoming data
$validated = $request->validate([
'title' => 'required|string|max:255',
'description' => 'nullable|string|max:5000',
'priority' => 'required|in:low,medium,high',
'due_date' => 'nullable|date|after_or_equal:today',
]);
// Create the task linked to the user
$request->user()->tasks()->create($validated);
return redirect()
->route('tasks.index')
->with('success', 'Task created successfully.');
}
// Display a task
public function show(Task $task): View
{
// Verify user ownership
Gate::authorize('view', $task);
return view('tasks.show', compact('task'));
}
// Edit form
public function edit(Task $task): View
{
Gate::authorize('update', $task);
return view('tasks.edit', compact('task'));
}
// Update a task
public function update(Request $request, Task $task): RedirectResponse
{
Gate::authorize('update', $task);
$validated = $request->validate([
'title' => 'required|string|max:255',
'description' => 'nullable|string|max:5000',
'status' => 'required|in:pending,in_progress,completed',
'priority' => 'required|in:low,medium,high',
'due_date' => 'nullable|date',
]);
// Update completed_at if status = completed
if ($validated['status'] === Task::STATUS_COMPLETED && !$task->completed_at) {
$validated['completed_at'] = now();
}
$task->update($validated);
return redirect()
->route('tasks.index')
->with('success', 'Task updated.');
}
// Delete a task
public function destroy(Task $task): RedirectResponse
{
Gate::authorize('delete', $task);
$task->delete();
return redirect()
->route('tasks.index')
->with('success', 'Task deleted.');
}
// Mark as completed (quick action)
public function complete(Task $task): RedirectResponse
{
Gate::authorize('update', $task);
$task->markAsCompleted();
return back()->with('success', 'Task completed!');
}
}Controller ใช้ Gate สำหรับการอนุญาต Validation ในตัว และ Route Model Binding สำหรับโค้ดที่กระชับและปลอดภัย
การกำหนด Route
Route กำหนด URL และเชื่อมโยงกับ Action ของ Controller Laravel 11 รวมศูนย์ Route ใน routes/web.php
<?php
// routes/web.php
use App\Http\Controllers\TaskController;
use App\Http\Controllers\ProfileController;
use Illuminate\Support\Facades\Route;
// Public homepage
Route::get('/', function () {
return view('welcome');
});
// Routes protected by authentication
Route::middleware(['auth', 'verified'])->group(function () {
// Dashboard with statistics
Route::get('/dashboard', function () {
$user = auth()->user();
return view('dashboard', [
'totalTasks' => $user->tasks()->count(),
'pendingTasks' => $user->tasks()->pending()->count(),
'completedTasks' => $user->tasks()->completed()->count(),
'overdueTasks' => $user->tasks()->overdue()->count(),
]);
})->name('dashboard');
// RESTful routes for tasks
Route::resource('tasks', TaskController::class);
// Quick action to complete a task
Route::patch('/tasks/{task}/complete', [TaskController::class, 'complete'])
->name('tasks.complete');
// Profile routes (generated by Breeze)
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});
// Authentication routes (generated by Breeze)
require __DIR__.'/auth.php';เมธอด Route::resource() สร้าง Route RESTful มาตรฐานเจ็ดเส้นทางโดยอัตโนมัติ: index, create, store, show, edit, update และ destroy
การตั้งค่า Policy สำหรับการอนุญาต
Policy รวมศูนย์ Logic การอนุญาตสำหรับแต่ละ Model กำหนดว่าใครสามารถทำอะไรกับทรัพยากรได้บ้าง
# terminal
# Generate the policy for Task
php artisan make:policy TaskPolicy --model=Task<?php
// app/Policies/TaskPolicy.php
namespace App\Policies;
use App\Models\Task;
use App\Models\User;
class TaskPolicy
{
// Check before all methods
// Returning true bypasses all checks (admin)
public function before(User $user, string $ability): ?bool
{
if ($user->is_admin) {
return true;
}
return null; // Continue to specific methods
}
// Can view the list of tasks
public function viewAny(User $user): bool
{
return true; // Any authenticated user
}
// Can view a specific task
public function view(User $user, Task $task): bool
{
return $user->id === $task->user_id;
}
// Can create a task
public function create(User $user): bool
{
return true;
}
// Can update a task
public function update(User $user, Task $task): bool
{
return $user->id === $task->user_id;
}
// Can delete a task
public function delete(User $user, Task $task): bool
{
return $user->id === $task->user_id;
}
// Can restore a soft-deleted task
public function restore(User $user, Task $task): bool
{
return $user->id === $task->user_id;
}
// Can permanently delete
public function forceDelete(User $user, Task $task): bool
{
return $user->id === $task->user_id;
}
}Laravel ค้นหา Policy โดยอัตโนมัติผ่านแบบแผนการตั้งชื่อ TaskPolicy จะถูกนำไปใช้กับ Model Task
Policy มีความสำคัญอย่างยิ่งต่อความปลอดภัย หากไม่มี Policy ผู้ใช้สามารถแก้ไข URL เพื่อเข้าถึงงานของผู้ใช้คนอื่นได้ ต้องตรวจสอบความเป็นเจ้าของทรัพยากรเสมอ
การสร้าง REST API
Laravel ทำให้การสร้าง RESTful API ง่ายขึ้นด้วย Route เฉพาะ, JSON Resource และ Sanctum สำหรับการยืนยันตัวตน
# terminal
# Install Sanctum (included by default since Laravel 11)
php artisan install:api
# This command:
# - Publishes Sanctum migrations
# - Adds the HasApiTokens trait to the User model
# - Configures API routes<?php
// app/Http/Controllers/Api/TaskController.php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Resources\TaskResource;
use App\Http\Resources\TaskCollection;
use App\Models\Task;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
class TaskController extends Controller
{
// Paginated list of tasks
public function index(Request $request): AnonymousResourceCollection
{
$tasks = $request->user()
->tasks()
->when($request->status, fn($q, $s) => $q->where('status', $s))
->when($request->priority, fn($q, $p) => $q->where('priority', $p))
->when($request->boolean('overdue'), fn($q) => $q->overdue())
->latest()
->paginate($request->input('per_page', 15));
return TaskResource::collection($tasks);
}
// Create a task
public function store(Request $request): JsonResponse
{
$validated = $request->validate([
'title' => 'required|string|max:255',
'description' => 'nullable|string|max:5000',
'priority' => 'required|in:low,medium,high',
'due_date' => 'nullable|date|after_or_equal:today',
]);
$task = $request->user()->tasks()->create($validated);
return response()->json([
'message' => 'Task created successfully.',
'data' => new TaskResource($task),
], 201);
}
// Display a task
public function show(Task $task): TaskResource
{
$this->authorize('view', $task);
return new TaskResource($task);
}
// Update a task
public function update(Request $request, Task $task): TaskResource
{
$this->authorize('update', $task);
$validated = $request->validate([
'title' => 'sometimes|required|string|max:255',
'description' => 'nullable|string|max:5000',
'status' => 'sometimes|required|in:pending,in_progress,completed',
'priority' => 'sometimes|required|in:low,medium,high',
'due_date' => 'nullable|date',
]);
if (isset($validated['status'])
&& $validated['status'] === Task::STATUS_COMPLETED
&& !$task->completed_at) {
$validated['completed_at'] = now();
}
$task->update($validated);
return new TaskResource($task->fresh());
}
// Delete a task
public function destroy(Task $task): JsonResponse
{
$this->authorize('delete', $task);
$task->delete();
return response()->json([
'message' => 'Task deleted successfully.',
]);
}
}API Resource สำหรับการแปลงข้อมูล
API Resource แปลง Model Eloquent เป็น JSON Response ที่มีโครงสร้าง ควบคุมข้อมูลที่เปิดเผยได้อย่างแม่นยำ
<?php
// app/Http/Resources/TaskResource.php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class TaskResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
'status' => $this->status,
'priority' => $this->priority,
'due_date' => $this->due_date?->format('Y-m-d'),
'is_overdue' => $this->is_overdue,
'completed_at' => $this->completed_at?->toISOString(),
'created_at' => $this->created_at->toISOString(),
'updated_at' => $this->updated_at->toISOString(),
// Conditional inclusion of the user
'user' => $this->whenLoaded('user', fn() => [
'id' => $this->user->id,
'name' => $this->user->name,
]),
];
}
}Route API พร้อมการยืนยันตัวตน Sanctum
<?php
// routes/api.php
use App\Http\Controllers\Api\TaskController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
// Route to retrieve the authenticated user
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:sanctum');
// API routes protected by Sanctum
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('tasks', TaskController::class);
// Dashboard statistics
Route::get('/dashboard/stats', function (Request $request) {
$user = $request->user();
return response()->json([
'total' => $user->tasks()->count(),
'pending' => $user->tasks()->pending()->count(),
'in_progress' => $user->tasks()->inProgress()->count(),
'completed' => $user->tasks()->completed()->count(),
'overdue' => $user->tasks()->overdue()->count(),
]);
});
});การทดสอบอัตโนมัติด้วย Pest
Laravel 11 รวม Pest PHP เป็นค่าเริ่มต้น เฟรมเวิร์กทดสอบที่สวยงามและมีความหมายชัดเจน การทดสอบช่วยให้มั่นใจว่าแอปพลิเคชันทำงานถูกต้องหลังจากทุกการเปลี่ยนแปลง
<?php
// tests/Feature/TaskTest.php
use App\Models\Task;
use App\Models\User;
// Test: a user can view their tasks
test('user can view their tasks', function () {
$user = User::factory()->create();
$tasks = Task::factory()->count(5)->for($user)->create();
$response = $this->actingAs($user)->get('/tasks');
$response->assertOk();
$response->assertViewHas('tasks');
});
// Test: a user can create a task
test('user can create a task', function () {
$user = User::factory()->create();
$response = $this->actingAs($user)->post('/tasks', [
'title' => 'New task',
'description' => 'Task description',
'priority' => 'high',
'due_date' => now()->addDays(7)->format('Y-m-d'),
]);
$response->assertRedirect('/tasks');
$this->assertDatabaseHas('tasks', [
'user_id' => $user->id,
'title' => 'New task',
'priority' => 'high',
]);
});
// Test: title validation required
test('task title is required', function () {
$user = User::factory()->create();
$response = $this->actingAs($user)->post('/tasks', [
'title' => '',
'priority' => 'medium',
]);
$response->assertSessionHasErrors('title');
});
// Test: a user cannot view another user's task
test('user cannot view another users task', function () {
$user = User::factory()->create();
$otherUser = User::factory()->create();
$task = Task::factory()->for($otherUser)->create();
$response = $this->actingAs($user)->get("/tasks/{$task->id}");
$response->assertForbidden();
});
// Test: mark a task as completed
test('user can complete a task', function () {
$user = User::factory()->create();
$task = Task::factory()->for($user)->create(['status' => 'pending']);
$response = $this->actingAs($user)->patch("/tasks/{$task->id}/complete");
$response->assertRedirect();
$task->refresh();
expect($task->status)->toBe('completed');
expect($task->completed_at)->not->toBeNull();
});
// API test: retrieve tasks
test('api returns paginated tasks', function () {
$user = User::factory()->create();
Task::factory()->count(20)->for($user)->create();
$response = $this->actingAs($user, 'sanctum')
->getJson('/api/tasks?per_page=10');
$response->assertOk()
->assertJsonCount(10, 'data')
->assertJsonStructure([
'data' => [
'*' => ['id', 'title', 'status', 'priority', 'due_date'],
],
'links',
'meta',
]);
});การรันการทดสอบด้วย Pest
# terminal
# Run all tests
php artisan test
# Tests with code coverage
php artisan test --coverage
# Tests for a specific file
php artisan test tests/Feature/TaskTest.php
# Parallel tests (faster)
php artisan test --parallelการปรับแต่งสำหรับ Production
ก่อนการ Deploy มีขั้นตอนการปรับแต่งหลายอย่างที่ช่วยเพิ่มประสิทธิภาพแอปพลิเคชัน Laravel
# terminal
# Cache configuration
php artisan config:cache
# Cache routes
php artisan route:cache
# Cache views
php artisan view:cache
# Optimize Composer autoloader
composer install --optimize-autoloader --no-dev
# Generate asset manifest
npm run buildการตั้งค่าไฟล์ .env สำหรับ Production
# .env.production
APP_NAME="Task Manager"
APP_ENV=production
APP_DEBUG=false
APP_URL=https://taskmanager.example.com
# Cache and session via Redis (recommended)
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
# Database
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=task_manager_prod
DB_USERNAME=app_user
DB_PASSWORD=strong_password_here
# Mail
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailgun.org
MAIL_PORT=587
MAIL_USERNAME=postmaster@taskmanager.example.com
MAIL_PASSWORD=secret
MAIL_ENCRYPTION=tlsห้าม Commit ไฟล์ .env เข้าสู่ Git Repository ใช้ .env.example เป็นเทมเพลต และตั้งค่าตัวแปรที่มีข้อมูลอ่อนไหวโดยตรงบนเซิร์ฟเวอร์ Production หรือผ่าน Secret Manager
สรุป
Laravel 11 ทำให้การพัฒนา PHP สมัยใหม่ง่ายขึ้นอย่างมากด้วยโครงสร้างที่กระชับและแบบแผนที่ชาญฉลาด คู่มือนี้ครอบคลุมพื้นฐานสำหรับการสร้างแอปพลิเคชันสมบูรณ์: Model Eloquent, ระบบยืนยันตัวตน, Controller แบบ RESTful, Policy สำหรับการอนุญาต, API ด้วย Sanctum และการทดสอบอัตโนมัติ
เช็คลิสต์สำหรับแอปพลิเคชัน Laravel คุณภาพ
- ใช้ Migration สำหรับทุกการเปลี่ยนแปลง Schema
- ใช้ Policy เพื่อรักษาความปลอดภัยการเข้าถึงทรัพยากร
- Validate ข้อมูลนำเข้าทั้งหมดใน Controller
- ใช้ API Resource เพื่อควบคุมข้อมูลที่เปิดเผย
- เขียนการทดสอบสำหรับฟีเจอร์สำคัญ
- ตั้งค่า Cache และการปรับแต่งก่อน Deploy
- รักษาความปลอดภัยตัวแปรสภาพแวดล้อมที่มีข้อมูลอ่อนไหว
เริ่มฝึกซ้อมเลย!
ทดสอบความรู้ของคุณด้วยตัวจำลองสัมภาษณ์และแบบทดสอบเทคนิคครับ
ระบบนิเวศ Laravel ยังคงพัฒนาอย่างต่อเนื่องด้วยแพ็กเกจเช่น Livewire สำหรับอินเทอร์เฟซแบบ Reactive, Horizon สำหรับจัดการ Queue และ Octane สำหรับประสิทธิภาพที่โดดเด่น การเชี่ยวชาญพื้นฐานเหล่านี้เปิดเส้นทางสู่แอปพลิเคชัน PHP ที่แข็งแกร่งและบำรุงรักษาง่าย
แท็ก
แชร์
บทความที่เกี่ยวข้อง

Symfony 7 กับ API Platform: แนวทางปฏิบัติที่ดีที่สุดสำหรับ REST API
คู่มือเชิงลึกสำหรับการสร้าง REST API ด้วย Symfony 7 และ API Platform 4 ครอบคลุม Resource configuration, State Processor, Serialization Groups, Security และการปรับแต่ง performance ด้วยตัวอย่างโค้ดที่ใช้งานได้จริง

NestJS: สร้าง REST API ที่สมบูรณ์ตั้งแต่เริ่มต้น
คู่มือฉบับสมบูรณ์สำหรับการสร้าง REST API ระดับมืออาชีพด้วย NestJS ครอบคลุม Controller, Service, Module, การตรวจสอบข้อมูลด้วย class-validator และการจัดการข้อผิดพลาด