侧边栏壁纸
博主头像
云BLOG 博主等级

行动起来,活在当下

  • 累计撰写 318 篇文章
  • 累计创建 6 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

用thinkphp8+layui2.11来开发个后台管理系统,请帮我规划,按最新2025年的技术开发

Administrator
2025-09-30 / 0 评论 / 0 点赞 / 0 阅读 / 0 字

我想用thinkphp8+layui2.11来开发个后台管理系统,请帮我规划,按最新2025年的技术开发

ThinkPHP8 + Layui2.11 后台管理系统开发规划(2025版)

一、技术栈选型

后端技术栈

- ThinkPHP 8.0.x (PHP 8.1+)
- MySQL 8.0+ / MariaDB 10.6+
- Redis 7.0+ (缓存/队列)
- Composer 2.x (依赖管理)

前端技术栈

- Layui 2.11
- jQuery 3.7+
- ES6+ JavaScript
- CSS3 + Less/Sass
- Axios (Ajax请求)

开发环境

- PHP 8.1+ (推荐 8.2+)
- Nginx 1.24+ / Apache 2.4+
- Node.js 20+ (前端构建工具)
- Git (版本控制)

二、项目目录结构

project/
├── app/                          # 应用目录
│   ├── admin/                    # 后台模块
│   │   ├── controller/          # 控制器
│   │   │   ├── Auth.php         # 登录认证
│   │   │   ├── Index.php        # 首页
│   │   │   ├── System.php       # 系统管理
│   │   │   ├── User.php         # 用户管理
│   │   │   ├── Role.php         # 角色管理
│   │   │   └── Menu.php         # 菜单管理
│   │   ├── model/               # 模型
│   │   ├── validate/            # 验证器
│   │   ├── service/             # 业务逻辑层
│   │   ├── middleware/          # 中间件
│   │   └── common.php           # 公共函数
│   ├── api/                      # API模块(可选)
│   ├── common/                   # 公共模块
│   │   ├── model/               # 公共模型
│   │   ├── service/             # 公共服务
│   │   └── library/             # 类库
│   ├── ExceptionHandle.php      # 异常处理
│   ├── Request.php              # 请求类
│   └── event.php                # 事件定义
├── config/                       # 配置目录
│   ├── app.php                  # 应用配置
│   ├── cache.php                # 缓存配置
│   ├── database.php             # 数据库配置
│   ├── filesystem.php           # 文件系统
│   ├── log.php                  # 日志配置
│   ├── middleware.php           # 中间件配置
│   └── route.php                # 路由配置
├── public/                       # 公共资源目录
│   ├── index.php                # 入口文件
│   ├── static/                  # 静态资源
│   │   ├── admin/               # 后台静态资源
│   │   │   ├── css/
│   │   │   ├── js/
│   │   │   ├── images/
│   │   │   └── layui/           # Layui框架
│   │   └── uploads/             # 上传文件
│   └── .htaccess
├── runtime/                      # 运行时目录
├── vendor/                       # 第三方类库
├── view/                         # 视图目录
│   └── admin/                   # 后台视图
│       ├── layout/              # 布局模板
│       │   ├── layout.html      # 主布局
│       │   └── iframe.html      # iframe布局
│       ├── index/               # 首页视图
│       ├── auth/                # 登录视图
│       ├── user/                # 用户管理
│       ├── role/                # 角色管理
│       └── menu/                # 菜单管理
├── route/                        # 路由目录
│   └── admin.php                # 后台路由
├── .env                          # 环境变量
├── composer.json                 # Composer配置
└── think                         # 命令行工具

三、核心功能模块

1. 基础架构模块

// 功能清单
✓ 用户认证(JWT Token / Session)
✓ 权限管理(RBAC - 角色权限控制)
✓ 菜单管理(动态菜单树)
✓ 操作日志(用户行为追踪)
✓ 数据字典
✓ 系统配置
✓ 文件上传(本地/OSS)
✓ 定时任务

2. 系统管理模块

✓ 管理员管理
✓ 角色管理
✓ 权限管理
✓ 部门管理
✓ 岗位管理
✓ 菜单管理
✓ 参数配置
✓ 通知公告

3. 监控模块

✓ 在线用户
✓ 操作日志
✓ 登录日志
✓ 系统监控
✓ 数据监控

四、数据库设计

核心数据表

-- 管理员表
CREATE TABLE `admin_user` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(255) NOT NULL COMMENT '密码',
  `nickname` varchar(50) DEFAULT NULL COMMENT '昵称',
  `avatar` varchar(255) DEFAULT NULL COMMENT '头像',
  `email` varchar(100) DEFAULT NULL COMMENT '邮箱',
  `mobile` varchar(20) DEFAULT NULL COMMENT '手机号',
  `dept_id` int DEFAULT NULL COMMENT '部门ID',
  `status` tinyint DEFAULT '1' COMMENT '状态:0禁用,1正常',
  `login_ip` varchar(50) DEFAULT NULL COMMENT '最后登录IP',
  `login_time` datetime DEFAULT NULL COMMENT '最后登录时间',
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `delete_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='管理员表';

-- 角色表
CREATE TABLE `admin_role` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL COMMENT '角色名称',
  `code` varchar(50) NOT NULL COMMENT '角色标识',
  `sort` int DEFAULT '0' COMMENT '排序',
  `status` tinyint DEFAULT '1' COMMENT '状态',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';

-- 菜单表
CREATE TABLE `admin_menu` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `pid` int DEFAULT '0' COMMENT '父ID',
  `type` tinyint DEFAULT '1' COMMENT '类型:1目录,2菜单,3按钮',
  `title` varchar(50) NOT NULL COMMENT '菜单名称',
  `icon` varchar(50) DEFAULT NULL COMMENT '图标',
  `path` varchar(200) DEFAULT NULL COMMENT '路由地址',
  `component` varchar(200) DEFAULT NULL COMMENT '组件路径',
  `permission` varchar(100) DEFAULT NULL COMMENT '权限标识',
  `sort` int DEFAULT '0' COMMENT '排序',
  `visible` tinyint DEFAULT '1' COMMENT '是否显示',
  `status` tinyint DEFAULT '1' COMMENT '状态',
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='菜单表';

-- 权限关联表
CREATE TABLE `admin_role_menu` (
  `role_id` int NOT NULL,
  `menu_id` int NOT NULL,
  PRIMARY KEY (`role_id`,`menu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色菜单关联表';

-- 用户角色关联表
CREATE TABLE `admin_user_role` (
  `user_id` int NOT NULL,
  `role_id` int NOT NULL,
  PRIMARY KEY (`user_id`,`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户角色关联表';

-- 操作日志表
CREATE TABLE `admin_log` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int DEFAULT NULL COMMENT '用户ID',
  `username` varchar(50) DEFAULT NULL COMMENT '用户名',
  `module` varchar(50) DEFAULT NULL COMMENT '模块',
  `action` varchar(50) DEFAULT NULL COMMENT '操作',
  `method` varchar(20) DEFAULT NULL COMMENT '请求方式',
  `url` varchar(500) DEFAULT NULL COMMENT '请求URL',
  `ip` varchar(50) DEFAULT NULL COMMENT 'IP地址',
  `params` text COMMENT '请求参数',
  `result` text COMMENT '返回结果',
  `status` tinyint DEFAULT '1' COMMENT '状态:0失败,1成功',
  `error_msg` text COMMENT '错误信息',
  `create_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_user_id` (`user_id`),
  KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作日志表';

五、核心代码实现

1. 基础控制器

<?php
// app/admin/controller/Base.php
namespace app\admin\controller;

use think\App;
use think\facade\Session;

abstract class Base
{
    protected $app;
    protected $request;
    protected $middleware = ['auth'];
    
    // 无需登录的方法
    protected $noNeedLogin = [];
    // 无需权限的方法
    protected $noNeedRight = [];
    
    public function __construct(App $app)
    {
        $this->app = $app;
        $this->request = $this->app->request;
        
        // 初始化
        $this->initialize();
    }
    
    protected function initialize()
    {
        // 检查登录
        $action = $this->request->action();
        if (!in_array($action, $this->noNeedLogin)) {
            $this->checkLogin();
        }
        
        // 检查权限
        if (!in_array($action, $this->noNeedRight)) {
            $this->checkAuth();
        }
    }
    
    protected function checkLogin()
    {
        if (!Session::has('admin_user_id')) {
            if ($this->request->isAjax()) {
                return json(['code' => 401, 'msg' => '请先登录']);
            }
            redirect('/admin/auth/login')->send();
            exit;
        }
    }
    
    protected function checkAuth()
    {
        // 权限验证逻辑
    }
    
    protected function success($msg = '操作成功', $data = [], $code = 200)
    {
        return json(['code' => $code, 'msg' => $msg, 'data' => $data]);
    }
    
    protected function error($msg = '操作失败', $data = [], $code = 400)
    {
        return json(['code' => $code, 'msg' => $msg, 'data' => $data]);
    }
}

2. 登录控制器

<?php
// app/admin/controller/Auth.php
namespace app\admin\controller;

use app\admin\model\AdminUser;
use think\facade\Session;

class Auth extends Base
{
    protected $noNeedLogin = ['login', 'captcha'];
    
    public function login()
    {
        if ($this->request->isPost()) {
            $username = $this->request->post('username');
            $password = $this->request->post('password');
            
            $user = AdminUser::where('username', $username)->find();
            if (!$user) {
                return $this->error('用户不存在');
            }
            
            if (!password_verify($password, $user->password)) {
                return $this->error('密码错误');
            }
            
            if ($user->status != 1) {
                return $this->error('账号已被禁用');
            }
            
            // 更新登录信息
            $user->login_ip = $this->request->ip();
            $user->login_time = date('Y-m-d H:i:s');
            $user->save();
            
            // 保存会话
            Session::set('admin_user_id', $user->id);
            Session::set('admin_username', $user->username);
            
            return $this->success('登录成功', ['url' => '/admin/index/index']);
        }
        
        return view();
    }
    
    public function logout()
    {
        Session::clear();
        return $this->success('退出成功', ['url' => '/admin/auth/login']);
    }
}

3. RBAC权限服务

<?php
// app/common/service/AuthService.php
namespace app\common\service;

use app\admin\model\AdminUser;
use think\facade\Cache;

class AuthService
{
    /**
     * 获取用户权限
     */
    public static function getUserPermissions($userId)
    {
        $cacheKey = 'user_permissions_' . $userId;
        
        return Cache::remember($cacheKey, function() use ($userId) {
            $user = AdminUser::with(['roles.menus'])->find($userId);
            $permissions = [];
            
            foreach ($user->roles as $role) {
                foreach ($role->menus as $menu) {
                    if ($menu->permission) {
                        $permissions[] = $menu->permission;
                    }
                }
            }
            
            return array_unique($permissions);
        }, 3600);
    }
    
    /**
     * 检查权限
     */
    public static function checkPermission($userId, $permission)
    {
        $permissions = self::getUserPermissions($userId);
        return in_array($permission, $permissions);
    }
    
    /**
     * 获取用户菜单树
     */
    public static function getUserMenuTree($userId)
    {
        $cacheKey = 'user_menu_tree_' . $userId;
        
        return Cache::remember($cacheKey, function() use ($userId) {
            // 查询用户拥有的菜单
            $menus = self::getUserMenus($userId);
            // 构建树形结构
            return self::buildMenuTree($menus);
        }, 3600);
    }
    
    private static function buildMenuTree($menus, $pid = 0)
    {
        $tree = [];
        foreach ($menus as $menu) {
            if ($menu['pid'] == $pid) {
                $children = self::buildMenuTree($menus, $menu['id']);
                if ($children) {
                    $menu['children'] = $children;
                }
                $tree[] = $menu;
            }
        }
        return $tree;
    }
}

六、前端布局实现

1. 主布局文件

<!-- view/admin/layout/layout.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>{$site_name|default='后台管理系统'}</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">
    <link rel="stylesheet" href="/static/admin/layui/css/layui.css">
    <link rel="stylesheet" href="/static/admin/css/admin.css">
</head>
<body>
    <div class="layui-layout layui-layout-admin">
        <!-- 头部 -->
        <div class="layui-header">
            <div class="layui-logo layui-hide-xs">
                <span>{$site_name|default='后台管理'}</span>
            </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"></i>
                    </a>
                </li>
            </ul>
            
            <ul class="layui-nav layui-layout-right">
                <li class="layui-nav-item" lay-unselect>
                    <a href="javascript:;">
                        <cite>{:session('admin_username')}</cite>
                    </a>
                    <dl class="layui-nav-child">
                        <dd><a href="/admin/user/profile">基本资料</a></dd>
                        <dd><a href="/admin/auth/logout">退出</a></dd>
                    </dl>
                </li>
            </ul>
        </div>
        
        <!-- 侧边菜单 -->
        <div class="layui-side layui-side-menu">
            <div class="layui-side-scroll">
                <div class="layui-logo">
                    <span>后台系统</span>
                </div>
                <ul class="layui-nav layui-nav-tree" lay-filter="menu">
                    {volist name="menus" id="menu"}
                    <li class="layui-nav-item">
                        {if condition="isset($menu['children'])"}
                        <a href="javascript:;">
                            <i class="layui-icon {$menu.icon}"></i>
                            <cite>{$menu.title}</cite>
                        </a>
                        <dl class="layui-nav-child">
                            {volist name="menu.children" id="child"}
                            <dd>
                                <a href="{$child.path}" lay-id="{$child.id}">
                                    {$child.title}
                                </a>
                            </dd>
                            {/volist}
                        </dl>
                        {else/}
                        <a href="{$menu.path}" lay-id="{$menu.id}">
                            <i class="layui-icon {$menu.icon}"></i>
                            <cite>{$menu.title}</cite>
                        </a>
                        {/if}
                    </li>
                    {/volist}
                </ul>
            </div>
        </div>
        
        <!-- 主体内容 -->
        <div class="layui-body">
            <div class="layadmin-tabsbody-item layui-show">
                <iframe src="/admin/index/home" frameborder="0" class="layadmin-iframe"></iframe>
            </div>
        </div>
        
        <!-- 底部 -->
        <div class="layui-footer">
            <p>&copy; 2025 后台管理系统</p>
        </div>
    </div>
    
    <script src="/static/admin/layui/layui.js"></script>
    <script src="/static/admin/js/admin.js"></script>
</body>
</html>

2. 登录页面

<!-- view/admin/auth/login.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>登录 - 后台管理系统</title>
    <link rel="stylesheet" href="/static/admin/layui/css/layui.css">
    <style>
        .login-container {
            width: 100%;
            height: 100vh;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            display: flex;
            justify-content: center;
            align-items: center;
        }
        .login-box {
            width: 400px;
            background: #fff;
            border-radius: 8px;
            padding: 40px;
            box-shadow: 0 15px 25px rgba(0,0,0,.2);
        }
        .login-title {
            text-align: center;
            font-size: 24px;
            margin-bottom: 30px;
            color: #333;
        }
    </style>
</head>
<body>
    <div class="login-container">
        <div class="login-box">
            <h2 class="login-title">后台管理系统</h2>
            <form class="layui-form" lay-filter="loginForm">
                <div class="layui-form-item">
                    <label class="layui-icon layui-icon-username"></label>
                    <input type="text" name="username" placeholder="用户名" 
                           autocomplete="off" class="layui-input" lay-verify="required">
                </div>
                <div class="layui-form-item">
                    <label class="layui-icon layui-icon-password"></label>
                    <input type="password" name="password" placeholder="密码" 
                           autocomplete="off" class="layui-input" lay-verify="required">
                </div>
                <div class="layui-form-item">
                    <button class="layui-btn layui-btn-fluid" lay-submit lay-filter="login">
                        登 录
                    </button>
                </div>
            </form>
        </div>
    </div>
    
    <script src="/static/admin/layui/layui.js"></script>
    <script>
    layui.use(['form', 'layer'], function(){
        var form = layui.form;
        var layer = layui.layer;
        
        form.on('submit(login)', function(data){
            $.ajax({
                url: '/admin/auth/login',
                type: 'POST',
                data: data.field,
                success: function(res) {
                    if (res.code === 200) {
                        layer.msg(res.msg, {icon: 1});
                        setTimeout(function(){
                            location.href = res.data.url;
                        }, 1000);
                    } else {
                        layer.msg(res.msg, {icon: 2});
                    }
                }
            });
            return false;
        });
    });
    </script>
</body>
</html>

七、开发规范

1. 命名规范

- 数据库表名:小写+下划线,如 admin_user
- 模型类名:大驼峰,如 AdminUser
- 控制器:大驼峰,如 UserController
- 方法名:小驼峰,如 getUserList
- 变量名:小驼峰,如 $userId

2. 注释规范

/**
 * 获取用户列表
 * @param int $page 页码
 * @param int $limit 每页数量
 * @return array
 */
public function getUserList($page = 1, $limit = 10)
{
    // 实现代码
}

3. 接口返回规范

{
    "code": 200,
    "msg": "操作成功",
    "data": {},
    "timestamp": 1704038400
}

八、安全建议

  1. 密码加密:使用 password_hash()password_verify()

  2. 防SQL注入:使用参数绑定

  3. XSS防护:输出时使用 htmlspecialchars()

  4. CSRF防护:使用Token验证

  5. 文件上传:限制文件类型和大小

  6. API接口:使用JWT或签名验证

  7. 敏感操作:记录操作日志

  8. 定期备份:数据库定时备份

九、性能优化

  1. 数据库优化:合理使用索引,避免N+1查询

  2. 缓存策略:Redis缓存热点数据

  3. 静态资源:CDN加速

  4. 代码优化:使用队列处理耗时任务

  5. 日志分级:生产环境关闭调试日志

十、部署建议

# 1. 环境要求
PHP >= 8.1
MySQL >= 8.0
Redis >= 7.0
Nginx >= 1.24

# 2. 安装依赖
composer install --no-dev

# 3. 配置权限
chmod -R 755 runtime
chmod -R 755 public/uploads

# 4. 配置伪静态(Nginx)
location / {
    if (!-e $request_filename) {
        rewrite ^(.*)$ /index.php?s=$1 last;
    }
}

# 5. 启动队列
php think queue:work

这套方案采用了2025年最新的技术标准,结合了ThinkPHP8的新特性和Layui的UI体验,可以快速构建一个现代化的后台管理系统。需要我详细展开哪个模块的实现吗?

八、安全建议 密码加密:使用 password_hash() 和 password_verify() 防SQL注入:使用参数绑定 XSS防护:输出时使用 htmlspecialchars() CSRF防护:使用Token验证 文件上传:限制文件类型和大小 API接口:使用JWT或签名验证 敏感操作:记录操作日志 定期备份:数据库定时备份 九、性能优化 数据库优化:合理使用索引,避免N+1查询 缓存策略:Redis缓存热点数据 静态资源:CDN加速 代码优化:使用队列处理耗时任务 日志分级:生产环境关闭调试日志 这些你能给出代码吗?左侧导航菜单根据后台登录账号的权限来显示。帮下一个统计的base控制器加强版,主要包括增删查改的功能增强。全局能调用,前端通用头部和脚,每个页面只要写布局就可以了。

根据您的需求,以下是针对安全建议、性能优化、权限控制、增强版Base控制器、全局通用头部和尾部的实现方案:

八、安全建议

1. 密码加密:使用 password_hash()password_verify()

在用户注册时,使用 password_hash() 对密码进行加密存储;在用户登录时,使用 password_verify() 验证密码。

// 注册时
$password = 'user_password';
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);

// 登录时
if (password_verify($password, $hashedPassword)) {
    // 密码正确
} else {
    // 密码错误
}

2. 防SQL注入:使用参数绑定

使用 ThinkPHP 的查询构建器,自动处理参数绑定,防止 SQL 注入。

// 查询用户
$user = Db::name('user')->where('id', $userId)->find();

在此示例中,$userId 会自动绑定,防止 SQL 注入。

3. XSS防护:输出时使用 htmlspecialchars()

在输出用户输入的内容时,使用 htmlspecialchars() 转义特殊字符,防止 XSS 攻击。

// 输出用户评论
echo htmlspecialchars($userComment, ENT_QUOTES, 'UTF-8');

4. CSRF防护:使用 Token 验证

在表单中添加隐藏的 Token 字段,提交时验证 Token,防止 CSRF 攻击。

// 生成 Token
$token = bin2hex(random_bytes(32));
$_SESSION['csrf_token'] = $token;

// 表单中添加隐藏字段
<input type="hidden" name="csrf_token" value="<?= $token ?>">

// 提交时验证 Token
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
    // Token 无效,拒绝请求
}

5. 文件上传:限制文件类型和大小

在处理文件上传时,限制文件类型和大小,防止恶意文件上传。

// 允许的文件类型
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
// 最大文件大小(字节)
$maxSize = 2 * 1024 * 1024; // 2MB

// 上传文件
$file = request()->file('image');
if ($file) {
    $info = $file->validate(['ext' => 'jpg,png,gif', 'size' => $maxSize])->move('uploads');
    if ($info) {
        // 上传成功
    } else {
        // 上传失败
        echo $file->getError();
    }
}

6. API接口:使用 JWT 或签名验证

使用 JWT(JSON Web Token)进行 API 接口的身份验证。

use \Firebase\JWT\JWT;

// 生成 JWT
$key = 'your_secret_key';
$payload = [
    'iss' => 'your_issuer',
    'aud' => 'your_audience',
    'iat' => time(),
    'exp' => time() + 3600, // 1小时有效期
    'data' => [
        'userId' => $userId,
        'username' => $username,
    ],
];
$jwt = JWT::encode($payload, $key);

// 验证 JWT
try {
    $decoded = JWT::decode($jwt, $key, ['HS256']);
    // 验证通过
} catch (Exception $e) {
    // 验证失败
}

请注意,使用 JWT 时需要安装 firebase/php-jwt 库。

7. 敏感操作:记录操作日志

在执行敏感操作时,记录操作日志,便于追踪和审计。

// 记录操作日志
Db::name('operation_log')->insert([
    'user_id' => $userId,
    'action' => 'delete_user',
    'target_id' => $targetUserId,
    'created_at' => date('Y-m-d H:i:s'),
]);

8. 定期备份:数据库定时备份

使用定时任务(如 cron)定期备份数据库。

# 每天凌晨2点备份数据库
0 2 * * * mysqldump -u username -p'password' database_name > /path/to/backup/database_name_$(date +\%F).sql

九、性能优化

1. 数据库优化:合理使用索引,避免 N+1 查询

确保数据库表有适当的索引,避免在循环中进行多次查询(N+1 查询问题)。

// 使用关联查询,避免 N+1 查询
$users = Db::name('user')
    ->alias('u')
    ->join('profile p', 'u.id = p.user_id')
    ->select();

2. 缓存策略:Redis 缓存热点数据

使用 Redis 缓存频繁访问的数据,减少数据库压力。

use think\facade\Cache;

// 设置缓存
Cache::set('user_profile_' . $userId, $profileData, 3600);

// 获取缓存
$profileData = Cache::get('user_profile_' . $userId);
if (!$profileData) {
    // 缓存不存在,查询数据库并更新缓存
    $profileData = Db::name('profile')->where('user_id', $userId)->find();
    Cache::set('user_profile_' . $userId, $profileData, 3600);
}

3. 静态资源:CDN 加速

将静态资源(如图片、CSS、JS)托管到 CDN,提升加载速度。

<!-- 使用 CDN 加载 jQuery -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>

4. 代码优化:使用队列处理耗时任务

将耗时的任务(如发送邮件、生成报告)放入队列,异步处理。

use think\queue\Job;

// 发送邮件任务
class SendEmailJob
{
    public function fire(Job $job, $data)
    {
        // 发送邮件逻辑
        // 如果发送成功,调用 $job->delete() 删除任务
        // 如果失败,调用 $job->release() 重新放入队列
    }
}

// 将任务推入队列
Queue::push(SendEmailJob::class, ['email' => $userEmail]);

5. 日志分级:生产环境关闭调试日志

在生产环境中,关闭调试日志,减少性能开销。

// config/log.php
return [
    'default' => [
        'type' => 'File',
        'path' => LOG_PATH,
        'level' => ['error', 'warning'],
    ],
];

十、权限控制:根据后台登录账号的权限显示左侧导航菜单

根据用户角色和权限动态生成左侧导航菜单。

// 获取用户角色和权限
$userRoles = Db::name('user_role')->where('user_id', $userId)->column('role_id');
$permissions = Db::name('role_permission')->whereIn('role_id', $userRoles)->column('permission');

// 获取菜单
$menus = Db::name('menu')->whereIn('permission', $permissions)->order('sort')->select();

// 构建菜单树
$menuTree = buildMenuTree($menus);

// 传递给视图
View::assign('menuTree', $menuTree);

十一、增强版 Base 控制器

提供通用的增删查改功能,方便各个控制器继承使用。

// app/admin/controller/BaseController.php
namespace app\admin\controller;

use think\Controller;
use think\Request;
use think\Db;

class BaseController extends Controller
{
    protected $model;

    public function __construct(Request $request)
    {
        parent::__construct($request);
        $this->model = Db::name($this->getModelName());
    }

    // 获取模型名称
    protected function getModelName()
    {
        $controller = $this->request->controller();
        return strtolower(preg_replace('/Controller$/', '', $controller));
    }

    // 列表
    public function index()
    {
        $data = $this->model->select();
        return json(['data' => $data]);
    }

    // 详情
    public function read($id)
    {
        $data = $this->model->find($id);
        return json(['data' => $data]);
    }

    // 创建
    public function create()
    {
        $data = $this->request->post();
        $id = $this->model->insertGetId($data);
        return json(['id' => $id]);
    }

    // 更新
    public function update($id)
    {
        $data = $this->request->put();
        $this->model->where('id', $id)->update($data);
        return json(['message' => '更新成功']);
    }

    // 删除
    public function delete($id)
    {
        $this->model->where('id', $id)->delete();
        return json(['message' => '删除成功']);
    }
}

各个控制器继承 BaseController,即可使用通用的增删查改功能。

十二、全局通用头部和尾部

在视图中引入通用的头部和尾部模板,减少重复代码。

<!-- 引入头 

0

评论区