第一个应用 #
一、项目概述 #
1.1 目标 #
创建一个简单的博客系统,包含以下功能:
| 功能 | 说明 |
|---|---|
| 文章列表 | 显示所有文章 |
| 创建文章 | 添加新文章 |
| 查看文章 | 查看文章详情 |
| 编辑文章 | 修改文章内容 |
| 删除文章 | 删除文章 |
1.2 涉及知识点 #
text
学习内容
├── 路由定义
├── 控制器创建
├── 视图渲染
├── 数据库迁移
├── Eloquent模型
├── 表单处理
└── 数据验证
二、创建项目 #
2.1 新建项目 #
bash
# 创建新项目
composer create-project laravel/laravel blog
# 进入项目目录
cd blog
# 启动开发服务器
php artisan serve
2.2 配置数据库 #
修改 .env 文件:
env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=blog
DB_USERNAME=root
DB_PASSWORD=your_password
2.3 生成应用密钥 #
bash
php artisan key:generate
三、创建数据库迁移 #
3.1 创建文章表迁移 #
bash
php artisan make:migration create_posts_table
3.2 编辑迁移文件 #
php
// database/migrations/xxxx_xx_xx_xxxxxx_create_posts_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('posts');
}
};
3.3 执行迁移 #
bash
php artisan migrate
四、创建模型 #
4.1 创建Post模型 #
bash
php artisan make:model Post
4.2 编辑模型 #
php
// app/Models/Post.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = [
'title',
'content',
];
}
五、创建控制器 #
5.1 创建资源控制器 #
bash
php artisan make:controller PostController --resource
5.2 实现控制器方法 #
php
// app/Http/Controllers/PostController.php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index()
{
$posts = Post::latest()->paginate(10);
return view('posts.index', compact('posts'));
}
public function create()
{
return view('posts.create');
}
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|max:255',
'content' => 'required',
]);
Post::create($validated);
return redirect()->route('posts.index')
->with('success', '文章创建成功!');
}
public function show(Post $post)
{
return view('posts.show', compact('post'));
}
public function edit(Post $post)
{
return view('posts.edit', compact('post'));
}
public function update(Request $request, Post $post)
{
$validated = $request->validate([
'title' => 'required|max:255',
'content' => 'required',
]);
$post->update($validated);
return redirect()->route('posts.index')
->with('success', '文章更新成功!');
}
public function destroy(Post $post)
{
$post->delete();
return redirect()->route('posts.index')
->with('success', '文章删除成功!');
}
}
六、定义路由 #
6.1 添加资源路由 #
php
// routes/web.php
use App\Http\Controllers\PostController;
Route::resource('posts', PostController::class);
6.2 查看路由列表 #
bash
php artisan route:list
输出结果:
text
+--------+-----------+------------------+---------------+
| Method | URI | Name | Action |
+--------+-----------+------------------+---------------+
| GET | posts | posts.index | PostController@index |
| GET | posts/create | posts.create | PostController@create |
| POST | posts | posts.store | PostController@store |
| GET | posts/{post} | posts.show | PostController@show |
| GET | posts/{post}/edit | posts.edit | PostController@edit |
| PUT | posts/{post} | posts.update | PostController@update |
| DELETE | posts/{post} | posts.destroy | PostController@destroy |
+--------+-----------+------------------+---------------+
七、创建视图 #
7.1 创建布局文件 #
blade
<!-- resources/views/layouts/app.blade.php -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title', '我的博客')</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="{{ route('posts.index') }}">我的博客</a>
</div>
</nav>
<main class="container py-4">
@if(session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
@yield('content')
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
7.2 文章列表视图 #
blade
<!-- resources/views/posts/index.blade.php -->
@extends('layouts.app')
@section('title', '文章列表')
@section('content')
<div class="d-flex justify-content-between align-items-center mb-4">
<h1>文章列表</h1>
<a href="{{ route('posts.create') }}" class="btn btn-primary">新建文章</a>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>标题</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
@foreach($posts as $post)
<tr>
<td>{{ $post->id }}</td>
<td>{{ $post->title }}</td>
<td>{{ $post->created_at->format('Y-m-d H:i') }}</td>
<td>
<a href="{{ route('posts.show', $post) }}" class="btn btn-sm btn-info">查看</a>
<a href="{{ route('posts.edit', $post) }}" class="btn btn-sm btn-warning">编辑</a>
<form action="{{ route('posts.destroy', $post) }}" method="POST" style="display:inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('确定删除?')">删除</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
{{ $posts->links() }}
@endsection
7.3 创建文章视图 #
blade
<!-- resources/views/posts/create.blade.php -->
@extends('layouts.app')
@section('title', '创建文章')
@section('content')
<h1 class="mb-4">创建文章</h1>
<form action="{{ route('posts.store') }}" method="POST">
@csrf
<div class="mb-3">
<label for="title" class="form-label">标题</label>
<input type="text" class="form-control @error('title') is-invalid @enderror"
id="title" name="title" value="{{ old('title') }}">
@error('title')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="content" class="form-label">内容</label>
<textarea class="form-control @error('content') is-invalid @enderror"
id="content" name="content" rows="10">{{ old('content') }}</textarea>
@error('content')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<button type="submit" class="btn btn-primary">提交</button>
<a href="{{ route('posts.index') }}" class="btn btn-secondary">取消</a>
</form>
@endsection
7.4 文章详情视图 #
blade
<!-- resources/views/posts/show.blade.php -->
@extends('layouts.app')
@section('title', $post->title)
@section('content')
<div class="mb-4">
<a href="{{ route('posts.index') }}" class="btn btn-secondary">返回列表</a>
<a href="{{ route('posts.edit', $post) }}" class="btn btn-warning">编辑</a>
</div>
<h1>{{ $post->title }}</h1>
<p class="text-muted">创建于 {{ $post->created_at->format('Y-m-d H:i') }}</p>
<hr>
<div class="content">
{{ $post->content }}
</div>
@endsection
7.5 编辑文章视图 #
blade
<!-- resources/views/posts/edit.blade.php -->
@extends('layouts.app')
@section('title', '编辑文章')
@section('content')
<h1 class="mb-4">编辑文章</h1>
<form action="{{ route('posts.update', $post) }}" method="POST">
@csrf
@method('PUT')
<div class="mb-3">
<label for="title" class="form-label">标题</label>
<input type="text" class="form-control @error('title') is-invalid @enderror"
id="title" name="title" value="{{ old('title', $post->title) }}">
@error('title')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="content" class="form-label">内容</label>
<textarea class="form-control @error('content') is-invalid @enderror"
id="content" name="content" rows="10">{{ old('content', $post->content) }}</textarea>
@error('content')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<button type="submit" class="btn btn-primary">更新</button>
<a href="{{ route('posts.index') }}" class="btn btn-secondary">取消</a>
</form>
@endsection
八、添加首页路由 #
8.1 修改欢迎页面 #
php
// routes/web.php
use App\Http\Controllers\PostController;
Route::get('/', function () {
return redirect()->route('posts.index');
});
Route::resource('posts', PostController::class);
九、数据填充 #
9.1 创建Seeder #
bash
php artisan make:seeder PostSeeder
9.2 编辑Seeder #
php
// database/seeders/PostSeeder.php
namespace Database\Seeders;
use App\Models\Post;
use Illuminate\Database\Seeder;
class PostSeeder extends Seeder
{
public function run()
{
$posts = [
[
'title' => 'Laravel入门教程',
'content' => '这是一篇关于Laravel入门的教程文章...',
],
[
'title' => 'Eloquent ORM详解',
'content' => 'Eloquent是Laravel的ORM实现...',
],
[
'title' => 'Blade模板引擎',
'content' => 'Blade是Laravel强大的模板引擎...',
],
];
foreach ($posts as $post) {
Post::create($post);
}
}
}
9.3 运行Seeder #
bash
php artisan db:seed --class=PostSeeder
十、测试应用 #
10.1 启动服务器 #
bash
php artisan serve
10.2 访问应用 #
text
打开浏览器访问: http://localhost:8000
10.3 功能测试清单 #
| 功能 | 测试项 |
|---|---|
| 列表 | 访问 /posts 查看文章列表 |
| 创建 | 点击"新建文章",填写表单提交 |
| 查看 | 点击"查看"按钮查看文章详情 |
| 编辑 | 点击"编辑"按钮修改文章 |
| 删除 | 点击"删除"按钮删除文章 |
十一、项目总结 #
11.1 文件清单 #
text
创建的文件
├── database/migrations/
│ └── xxxx_create_posts_table.php
├── app/Models/
│ └── Post.php
├── app/Http/Controllers/
│ └── PostController.php
├── resources/views/
│ ├── layouts/
│ │ └── app.blade.php
│ └── posts/
│ ├── index.blade.php
│ ├── create.blade.php
│ ├── show.blade.php
│ └── edit.blade.php
└── database/seeders/
└── PostSeeder.php
11.2 学到的知识点 #
| 知识点 | 说明 |
|---|---|
| 迁移 | 数据库表结构定义 |
| 模型 | Eloquent ORM使用 |
| 控制器 | 请求处理和响应 |
| 路由 | 资源路由定义 |
| 视图 | Blade模板渲染 |
| 验证 | 表单数据验证 |
| 表单 | CSRF保护和表单构建 |
11.3 下一步 #
恭喜你完成了第一个Laravel应用!接下来让我们深入学习 路由基础,掌握Laravel路由系统!
最后更新:2026-03-28