本教程将以 ThinkPHP 8Layui 为例,因为它在国内开发者中非常流行,且文档和组件丰富,非常适合快速开发。


教程总览

  1. 准备工作:环境搭建和项目初始化。
  2. 后台模板集成:下载并集成 Layui 模板到 ThinkPHP 项目。
  3. 后台布局搭建:创建主布局文件、侧边栏和头部。
  4. 后台登录功能:实现登录、验证码和会话控制。
  5. 后台首页:创建登录后的欢迎页面。
  6. 数据表格与CRUD:实现一个完整的数据列表、新增、编辑、删除功能。
  7. 常用功能补充:文件上传、富文本编辑器等。

第一步:准备工作

环境要求

  • PHP >= 7.2.5
  • Composer
  • Web 服务器 (Nginx/Apache)
  • 数据库 (MySQL 5.7+)

创建 ThinkPHP 项目

打开终端,使用 Composer 创建一个新的 ThinkPHP 项目。

# 创建一个名为 admin 的项目
composer create-project topthink/think admin
# 进入项目目录
cd admin

配置数据库

打开项目根目录下的 .env 文件,填入你的数据库信息。

[APP]
DEFAULT_TIMEZONE = Asia/Shanghai
[DATABASE]
TYPE = mysql
HOSTNAME = 127.0.0.1
DATABASE = think_admin  # 你的数据库名
USERNAME = root         # 你的数据库用户名
PASSWORD = root         # 你的数据库密码
HOSTPORT = 3306
CHARSET = utf8mb4
DEBUG = true

在 MySQL 中创建这个数据库 think_admin


第二步:集成后台模板 (Layui)

Layui 是一个自身模块化的前端 UI 框架,我们只需要下载它的核心文件即可。

下载 Layui

访问 Layui 官网,下载最新版。

放置文件

将下载的 layui 文件夹解压,并将其中的 dist 目录重命名为 layui,然后复制到 ThinkPHP 项目的 public 目录下。

你的项目结构会是这样:

admin/
├── app/
├── config/
├── public/
│   ├── layui/          <-- Layui 核心文件
│   ├── static/         <-- 项目其他静态文件
│   └── index.php       <-- 入口文件
├── route/
├── ...
└── vendor/

第三步:搭建后台布局

后台管理系统的布局通常是固定的,包含顶部导航栏、左侧菜单和主内容区,我们使用 ThinkPHP 的模板继承功能来实现。

创建布局文件

app/view 目录下创建 layout 文件夹,并在其中创建 main.html 文件,这个文件是我们的主布局。

app/view/layout/main.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">{block name="title"}ThinkPHP Admin{/block}</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <link rel="stylesheet" href="/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="/static/css/admin.css" media="all"> <!-- 我们可以自定义一些样式 -->
</head>
<body class="layui-layout-body">
    <div class="layui-layout layui-layout-admin">
        <!-- 顶部导航栏 -->
        <div class="layui-header">
            <div class="layui-logo">ThinkPHP 后台管理系统</div>
            <ul class="layui-nav layui-layout-left">
                <li class="layui-nav-item layadmin-flexible" lay-unselect>
                    <a href="javascript:;" layadmin-event="flexible" title="侧边伸缩">
                        <i class="layui-icon layui-icon-shrink-right" id="LAY_app_flexible"></i>
                    </a>
                </li>
            </ul>
            <ul class="layui-nav layui-layout-right">
                <li class="layui-nav-item">
                    <a href="javascript:;">
                        <img src="/static/images/avatar.jpg" class="layui-nav-img">
                        管理员
                    </a>
                    <dl class="layui-nav-child">
                        <dd><a lay-href="/profile/info">基本资料</a></dd>
                        <dd><a lay-href="/profile/password">修改密码</a></dd>
                        <hr>
                        <dd style="text-align: center;"><a href="/auth/logout">退出</a></dd>
                    </dl>
                </li>
            </ul>
        </div>
        <!-- 左侧导航区域 -->
        <div class="layui-side layui-side-menu">
            <div class="layui-side-scroll">
                <ul class="layui-nav layui-nav-tree" lay-shrink="all" id="LAY-system-side-menu" lay-filter="layadmin-system-side-menu">
                    <!-- 菜单项将通过 JS 动态加载,或者手动写死 -->
                    <li class="layui-nav-item">
                        <a href="javascript:;">控制台</a>
                        <dl class="layui-nav-child">
                            <dd><a lay-href="/dashboard/index">主页</a></dd>
                        </dl>
                    </li>
                    <li class="layui-nav-item">
                        <a href="javascript:;">用户管理</a>
                        <dl class="layui-nav-child">
                            <dd><a lay-href="/user/index">用户列表</a></dd>
                        </dl>
                    </li>
                </ul>
            </div>
        </div>
        <!-- 内容主体区域 -->
        <div class="layui-body" id="LAY_app_body">
            {block name="content"}{/block}
        </div>
        <!-- 辅助元素,一般用于移动设备下遮罩 -->
        <div class="layadmin-body-shade" layadmin-event="shade"></div>
    </div>
    <script src="/layui/layui.js"></script>
    <script>
    layui.config({
        base: '/static/js/' //静态资源所在路径
    }).extend({
        index: 'lib/index' //主入口模块
    }).use(['index', 'common']);
    </script>
    {block name="script"}{/block}
</body>
</html>

创建首页视图

app/view 下创建 dashboard 文件夹,并创建 index.html 文件。

app/view/dashboard/index.html

{extend name="layout/main" /}
{block name="title"}控制台 - ThinkPHP Admin{/block}
{block name="content"}
<div class="layui-fluid">
    <div class="layui-row layui-col-space15">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-header">欢迎使用 ThinkPHP 后台管理系统</div>
                <div class="layui-card-body">
                    <p>这是一个基于 ThinkPHP 8 + Layui 的后台管理模板。</p>
                </div>
            </div>
        </div>
    </div>
</div>
{/block}

第四步:实现后台登录功能

创建路由

route/app.php 中定义登录相关的路由。

<?php
use think\facade\Route;
// 登录相关路由组
Route::group('auth', function () {
    Route::get('login', 'AuthController/login');
    Route::post('login', 'AuthController/doLogin'); // 处理登录请求
    Route::get('logout', 'AuthController/logout');
});
// 后台需要登录验证的路由组
Route::group('admin', function () {
    Route::get('dashboard/index', 'DashboardController/index');
})->middleware(\app\http\middleware\CheckLogin::class); // 使用中间件检查登录

创建中间件

我们需要一个中间件来检查用户是否已登录。

# 创建中间件
php think make:middleware CheckLogin

编辑 app/middleware/CheckLogin.php:

<?php
declare(strict_types=1);
namespace app\middleware;
use think\facade\Session;
use think\Request;
use think\Response;
class CheckLogin
{
    /**
     * 处理请求
     *
     * @param Request $request
     * @param \Closure $next
     * @return Response
     */
    public function handle($request, \Closure $next)
    {
        // 检查 session