我们将使用 Laravel 作为 PHP 框架,虽然您提到了“模板”,但直接使用原生 PHP 写模板会比较混乱,而像 Laravel 这样的现代 MVC 框架,其“模板”系统(Blade)非常强大、优雅且安全,是当前行业的主流实践。

为什么选择 Laravel?
- MVC 架构:代码结构清晰,易于维护。
- Eloquent ORM:让数据库操作变得像“与对象对话”一样简单。
- Blade 模板引擎:提供强大的模板继承和组件功能。
- 强大的生态系统:有海量的扩展包,可以快速实现各种功能。
- 安全性高:内置了防止 SQL 注入、XSS 等攻击的机制。
第一步:环境准备
在开始之前,您需要准备好本地开发环境。
- PHP: 版本 >= 8.0
- Composer: PHP 的依赖管理工具。
- MySQL: 数据库服务。
- Web 服务器: Nginx 或 Apache (推荐使用集成环境如 XAMPP, WAMP, MAMP 或 Docker)。
第二步:安装 Laravel
Laravel 提供了一个非常方便的安装器。
-
全局安装 Laravel 安装器 (如果尚未安装):
composer global require laravel/installer
确保将
~/.composer/vendor/bin添加到您的 PATH 环境变量中。
(图片来源网络,侵删) -
创建一个新的 Laravel 项目:
laravel new my-website
或者使用 Composer:
composer create-project laravel/laravel my-website
-
进入项目目录:
cd my-website
-
启动开发服务器:
(图片来源网络,侵删)php artisan serve
现在在浏览器中访问
http://127.0.0.1:8000,您应该能看到 Laravel 的欢迎页面。
第三步:项目结构解析
Laravel 的目录结构非常清晰:
my-website/
├── app/ # 核心应用代码
│ ├── Http/
│ │ ├── Controllers/ # 控制器
│ │ └── Middleware/ # 中间件
│ ├── Models/ # 数据模型
│ └── Providers/ # 服务提供者
├── config/ # 配置文件
├── database/
│ ├── migrations/ # 数据库迁移文件
│ └── seeds/ # 数据库填充文件
├── public/ # Web 可访问的目录 (CSS, JS, 图片)
├── resources/
│ ├── views/ # Blade 模板文件
│ └── lang/ # 语言文件
├── routes/ # 路由定义文件
├── .env # 环境变量配置 (重要!)
└── composer.json # 项目依赖
第四步:配置数据库
-
创建数据库: 在您的 MySQL 管理工具 (如 phpMyAdmin) 中创建一个新的数据库,
my_website_db。 -
配置
.env文件: 在项目根目录下,找到.env文件并修改数据库配置:DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=my_website_db DB_USERNAME=your_mysql_username DB_PASSWORD=your_mysql_password
第五步:构建核心功能模块
我们将构建一个简单的博客系统作为示例,它包含文章列表、文章详情和后台管理。
数据库迁移
Laravel 使用迁移来管理数据库结构,我们创建一个 posts 表。
php artisan make:migration create_posts_table --create=posts
这会在 database/migrations/ 目录下创建一个新的文件,打开它并定义表结构:
// 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(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->boolean('is_published')->default(false);
$table->timestamps(); // 自动创建 created_at 和 updated_at
});
}
public function down(): void
{
Schema::dropIfExists('posts');
}
};
运行迁移来创建表:
php artisan migrate
创建模型
模型是与数据库表交互的类。
php artisan make:model Post
这会在 app/Models/Post.php 创建模型文件,我们可以在这里添加一些规则:
// app/Models/Post.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
// 定义哪些属性可以被批量赋值
protected $fillable = [
'title',
'content',
'is_published',
];
// 可以添加一个作用域,方便查询已发布的文章
public function scopePublished($query)
{
return $query->where('is_published', true);
}
}
定义路由
路由定义了 URL 如何映射到控制器。
打开 routes/web.php:
// routes/web.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;
// 前台路由
Route::get('/', [PostController::class, 'index'])->name('home');
Route::get('posts/{post:slug}', [PostController::class, 'show'])->name('posts.show');
// 后台路由组
Route::prefix('admin')->name('admin.')->middleware('auth')->group(function () {
Route::get('/posts', [PostController::class, 'index'])->name('posts.index');
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');
Route::delete('/posts/{post}', [PostController::class, 'destroy'])->name('posts.destroy');
});
// 简单的认证路由
require __DIR__.'/auth.php';
name()方法为路由命名,方便在模板中生成链接。middleware('auth')表示这些路由需要登录才能访问。
创建控制器
控制器处理业务逻辑。
php artisan make:controller PostController --resource
--resource 会自动生成处理 CRUD (增删改查) 操作的方法。
打开 app/Http/Controllers/PostController.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::published()->latest()->paginate(10);
return view('posts.index', compact('posts'));
}
// 显示单篇文章详情
public function show(Post $post)
{
return view('posts.show', compact('post'));
}
// 后台:显示文章列表
public function index()
{
$posts = Post::latest()->paginate(10);
return view('admin.posts.index', compact('posts'));
}
// 后台:显示创建文章的表单
public function create()
{
return view('admin.posts.create');
}
// 后台:保存新文章
public function store(Request $request)
{
$request->validate([
'title' => 'required|max:255',
'content' => 'required',
]);
Post::create($request->all());
return redirect()->route('admin.posts.index')
->with('success', '文章创建成功!');
}
// ... 其他后台方法 (edit, update, destroy) ...
// 逻辑类似,主要是处理表单验证和模型操作
}
创建视图 (Blade 模板)
视图是用户看到的 HTML 部分,我们将创建一个主布局文件和几个子页面。
a) 主布局文件 resources/views/layouts/app.blade.php
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">@yield('title', '我的网站')</title>
<!-- 引入一个 CSS 框架,如 Tailwind CSS 或 Bootstrap -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
@stack('styles')
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="{{ route('home') }}">我的网站</a>
<div class="collapse navbar-collapse">
<ul class="navbar-nav me-auto">
<li class="nav-item"><a class="nav-link" href="{{ route('home') }}">首页</a></li>
<!-- 后台链接,只有登录用户可见 -->
@auth
<li class="nav-item"><a class="nav-link" href="{{ route('admin.posts.index') }}">后台管理</a></li>
@endauth
</ul>
@guest
<a href="{{ route('login') }}" class="btn btn-outline-light">登录</a>
@else
<a href="{{ route('logout') }}"
class="btn btn-outline-light"
onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
退出
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
@csrf
</form>
@endguest
</div>
</div>
</nav>
<div class="container mt-4">
@if (session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
@yield('content')
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
@stack('scripts')
</body>
</html>
关键 Blade 指令:
@yield('title'): 定义一个可填充的区域,用于页面标题。@stack('styles') / @stack('scripts'): 允许子页面向布局中注入 CSS 或 JS 代码。@auth/@guest: 判断用户是否登录,显示不同的内容。@yield('content'): 这是主要内容区域,每个页面都会填充这里。
b) 前台文章列表 resources/views/posts/index.blade.php
@extends('layouts.app')
@section('title', '文章列表')
@section('content')
<h1>文章列表</h1>
@foreach ($posts as $post)
<article class="card mb-3">
<div class="card-body">
<h2 class="card-title">
<a href="{{ route('posts.show', $post) }}" class="text-decoration-none">
{{ $post->title }}
</a>
</h2>
<p class="card-text">{{ Str::limit($post->content, 100) }}</p>
<small class="text-muted">发布于: {{ $post->created_at->format('Y-m-d') }}</small>
</div>
</article>
@endforeach
{{ $posts->links() }} <!-- 分页链接 -->
@endsection
c) 前台文章详情 resources/views/posts/show.blade.php
@extends('layouts.app')
@section('title', $post->title)
@section('content')
<article>
<h1>{{ $post->title }}</h1>
<p class="text-muted">发布于: {{ $post->created_at->format('Y-m-d H:i') }}</p>
<hr>
<div class="content">
{!! $post->content !!} {!! !!} 使用 {!! !!} 安全地渲染 HTML 内容
</div>
</article>
@endsection
d) 后台文章列表 resources/views/admin/posts/index.blade.php
@extends('layouts.app')
@section('title', '管理文章')
@section('content')
<h1>管理文章</h1>
<a href="{{ route('admin.posts.create') }}" class="btn btn-primary mb-3">创建新文章</a>
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>标题</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->is_published ? '已发布' : '草稿' }}</td>
<td>{{ $post->created_at->format('Y-m-d') }}</td>
<td>
<a href="{{ route('admin.posts.edit', $post) }}" class="btn btn-sm btn-info">编辑</a>
<form action="{{ route('admin.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>
@endsection
第六步:用户认证
Laravel 提供了开箱即用的用户认证系统。
-
运行认证脚手架命令:
php artisan make:auth
注意:在新版 Laravel 中,这个命令被替换了,您需要安装
laravel/ui包。composer require laravel/ui php artisan ui bootstrap --auth npm install && npm run dev
这会自动生成登录、注册、密码重置等页面和相关的控制器、路由。
-
创建用户表: 运行迁移来创建
users表和相关的密码重置表。php artisan migrate
您就有了完整的用户注册、登录功能,之前我们在后台路由中使用的 middleware('auth') 现在已经可以正常工作了。
第七步:部署
当您的网站开发完成后,需要将其部署到服务器上。
- Git 版本控制: 将您的代码推送到 GitHub、GitLab 等平台。
- 服务器环境: 在您的服务器上安装 PHP, Nginx/Apache, MySQL, Composer。
- 拉取代码:
git clone <your-repo-url> - 安装依赖:
composer install --no-dev(生产环境不需要开发依赖) - 配置环境: 复制
.env.example到.env并修改数据库等配置。 - 生成应用密钥:
php artisan key:generate - 运行迁移:
php artisan migrate --force(生产环境需要--force) - 配置 Web 服务器: 将 Nginx/Apache 的
root指向public目录,并配置 URL 重写。
总结与扩展
您现在已经有了一个功能齐全的、基于 Laravel 的 PHP MySQL 网站模板,这个模板包含了:
- 清晰的 MVC 架构
- 数据库迁移和 Eloquent ORM
- 强大的 Blade 模板系统
- RESTful 路由设计
- 用户认证系统
- 前后台分离的示例
您可以基于此模板进行扩展:
- 添加更多功能: 如评论系统、标签、分类、用户角色等。
- 使用 API: 创建一个 API 控制器,为移动端提供数据。
- 优化性能: 学习使用缓存、队列、优化数据库查询等。
- 使用 Vue/React: 在
resources/js中集成前端框架,构建更动态的用户界面。
这个模板为您提供了一个坚实的基础,是构建现代 PHP 网站的绝佳起点。
