一、系统架构设计
本教程将基于ThinkPHP 6.1构建一个完整的企业级内容管理系统,采用多模块设计和前后端分离架构。
技术架构:
- 核心框架:ThinkPHP 6.1
- 前端架构:Vue3 + Element Plus
- 数据库:MySQL 8.0 + Redis
- 权限系统:RBAC权限模型
- 接口规范:RESTful API
核心功能模块:
- 多模块应用架构
- 可视化权限管理系统
- 内容模型动态扩展
- 高性能文件上传服务
- 多级缓存策略
二、项目初始化与配置
1. 环境准备与项目创建
# 安装ThinkPHP6
composer create-project topthink/think tp-cms
# 安装必要扩展
cd tp-cms
composer require topthink/think-multi-app
composer require topthink/think-captcha
composer require liliuwei/think-social
# 配置数据库
// config/database.php
return [
'connections' => [
'mysql' => [
'type' => 'mysql',
'hostname' => '127.0.0.1',
'database' => 'tp_cms',
'username' => 'root',
'password' => '',
'charset' => 'utf8mb4',
'debug' => true,
],
'redis' => [
'type' => 'redis',
'host' => '127.0.0.1',
'port' => 6379,
]
]
];
2. 多模块目录结构
tp-cms/
├── app/
│ ├── admin/ # 后台模块
│ │ ├── controller/
│ │ ├── model/
│ │ └── view/
│ ├── api/ # API模块
│ ├── common/ # 公共模块
│ │ ├── library/
│ │ ├── middleware/
│ │ └── service/
│ └── index/ # 前台模块
├── config/
├── public/
├── route/
├── extend/
└── runtime/
三、核心功能实现
1. RBAC权限系统
// app/admin/controller/Auth.php
namespace appadmincontroller;
use thinkfacadeDb;
use thinkfacadeSession;
class Auth extends BaseController
{
// 用户登录
public function login()
{
if ($this->request->isPost()) {
$data = $this->request->post();
// 验证码校验
if (!captcha_check($data['captcha'])) {
return json(['code'=>0, 'msg'=>'验证码错误']);
}
// 用户验证
$user = Db::name('admin_user')
->where('username', $data['username'])
->find();
if (!$user || !password_verify($data['password'], $user['password'])) {
return json(['code'=>0, 'msg'=>'用户名或密码错误']);
}
// 权限节点获取
$rules = $this->getUserRules($user['id']);
// 保存登录状态
Session::set('admin_user', [
'id' => $user['id'],
'username' => $user['username'],
'rules' => $rules
]);
return json(['code'=>1, 'msg'=>'登录成功']);
}
return $this->fetch();
}
// 获取用户权限节点
protected function getUserRules($uid)
{
$groups = Db::name('auth_group_access')
->alias('a')
->join('auth_group g', 'a.group_id=g.id')
->where('a.uid', $uid)
->column('g.rules');
$rules = [];
foreach ($groups as $group) {
$rules = array_merge($rules, explode(',', $group));
}
return array_unique($rules);
}
}
2. 权限验证中间件
// app/common/middleware/AuthCheck.php
namespace appcommonmiddleware;
use thinkfacadeSession;
class AuthCheck
{
public function handle($request, Closure $next)
{
$module = $request->module();
$controller = $request->controller();
$action = $request->action();
$rule = strtolower("{$module}/{$controller}/{$action}");
// 排除公开路由
$publicRules = ['admin/auth/login', 'admin/auth/logout'];
if (in_array($rule, $publicRules)) {
return $next($request);
}
// 验证登录
$user = Session::get('admin_user');
if (!$user) {
return redirect('/admin/auth/login');
}
// 超级管理员跳过验证
if ($user['id'] == 1) {
return $next($request);
}
// 权限验证
if (!in_array($rule, $user['rules'])) {
if ($request->isAjax()) {
return json(['code'=>0, 'msg'=>'无权限操作']);
} else {
return view('admin@public/error', ['msg'=>'无权限操作']);
}
}
return $next($request);
}
}
四、内容管理模块
1. 动态内容模型设计
// app/common/model/Content.php
namespace appcommonmodel;
use thinkModel;
class Content extends Model
{
// 内容模型映射
protected $modelMap = [
1 => 'Article',
2 => 'Product',
3 => 'Page'
];
// 获取内容模型实例
public function getModel($model_id)
{
if (!isset($this->modelMap[$model_id])) {
throw new Exception('内容模型不存在');
}
$class = 'appcommonmodel\' . $this->modelMap[$model_id];
return new $class;
}
// 保存内容
public function saveContent($data)
{
$model = $this->getModel($data['model_id']);
Db::startTrans();
try {
// 主表数据
$contentId = $this->insertGetId([
'model_id' => $data['model_id'],
'title' => $data['title'],
'create_time' => time()
]);
// 副表数据
$model->save([
'content_id' => $contentId,
'content' => $data['content']
]);
Db::commit();
return $contentId;
} catch (Exception $e) {
Db::rollback();
throw $e;
}
}
}
2. 文件上传服务
// app/common/service/Upload.php
namespace appcommonservice;
use thinkfacadeFilesystem;
use thinkfileUploadedFile;
class Upload
{
// 上传文件
public function upload($file, $type = 'image')
{
if (!$file instanceof UploadedFile) {
throw new Exception('上传文件无效');
}
// 验证文件类型
$mimeTypes = [
'image' => ['image/jpeg', 'image/png', 'image/gif'],
'file' => ['application/pdf', 'application/msword']
];
if (!in_array($file->getMime(), $mimeTypes[$type])) {
throw new Exception('不允许的文件类型');
}
// 生成保存路径
$saveName = Filesystem::disk('public')
->putFile($type, $file);
// 返回文件信息
return [
'name' => $file->getOriginalName(),
'path' => '/storage/' . $saveName,
'size' => $file->getSize(),
'type' => $file->getMime()
];
}
// 缩略图生成
public function thumb($path, $width = 300, $height = 300)
{
$image = thinkImage::open('.' . $path);
$thumbPath = str_replace('.', '_thumb.', $path);
$image->thumb($width, $height)->save('.' . $thumbPath);
return $thumbPath;
}
}
五、API接口开发
1. RESTful API设计
// app/api/controller/Article.php
namespace appapicontroller;
use thinkfacadeCache;
use appcommonmodelArticle as ArticleModel;
class Article
{
// 文章列表
public function index()
{
$page = $this->request->param('page/d', 1);
$size = $this->request->param('size/d', 10);
$cacheKey = "article_list_{$page}_{$size}";
$data = Cache::get($cacheKey);
if (!$data) {
$list = ArticleModel::where('status', 1)
->order('create_time', 'desc')
->paginate(['page'=>$page, 'list_rows'=>$size]);
$data = [
'code' => 1,
'data' => $list->items(),
'total' => $list->total()
];
Cache::set($cacheKey, $data, 3600);
}
return json($data);
}
// 文章详情
public function read($id)
{
$article = ArticleModel::find($id);
if (!$article) {
return json(['code'=>0, 'msg'=>'文章不存在']);
}
// 阅读量+1
$article->inc('views')->update();
return json(['code'=>1, 'data'=>$article]);
}
}
2. JWT认证实现
// app/api/middleware/JwtAuth.php
namespace appapimiddleware;
use thinkfacadeConfig;
use FirebaseJWTJWT;
use FirebaseJWTKey;
class JwtAuth
{
public function handle($request, Closure $next)
{
$token = $request->header('Authorization');
if (!$token) {
return json(['code'=>0, 'msg'=>'Token缺失'], 401);
}
try {
$config = Config::get('jwt');
$decoded = JWT::decode($token, new Key($config['key'], $config['alg']));
$request->user = $decoded;
} catch (Exception $e) {
return json(['code'=>0, 'msg'=>'Token无效'], 401);
}
return $next($request);
}
}
// 生成Token
public function login()
{
$username = $this->request->post('username');
$password = $this->request->post('password');
$user = Db::name('user')
->where('username', $username)
->find();
if (!$user || !password_verify($password, $user['password'])) {
return json(['code'=>0, 'msg'=>'用户名或密码错误']);
}
$payload = [
'iss' => 'tp-cms',
'iat' => time(),
'exp' => time() + 7200,
'uid' => $user['id'],
'name' => $user['username']
];
$token = JWT::encode($payload, Config::get('jwt.key'), Config::get('jwt.alg'));
return json(['code'=>1, 'token'=>$token]);
}
六、性能优化策略
1. 多级缓存方案
// app/common/service/CacheService.php
namespace appcommonservice;
use thinkfacadeCache;
use thinkfacadeConfig;
class CacheService
{
// 获取缓存数据
public function get($key, $callback = null, $ttl = 3600)
{
// 第一层:内存缓存
static $memoryCache = [];
if (isset($memoryCache[$key])) {
return $memoryCache[$key];
}
// 第二层:Redis缓存
$data = Cache::get($key);
if ($data !== null) {
$memoryCache[$key] = $data;
return $data;
}
// 第三层:数据库查询
if ($callback && is_callable($callback)) {
$data = call_user_func($callback);
$this->set($key, $data, $ttl);
return $data;
}
return null;
}
// 设置缓存
public function set($key, $data, $ttl = 3600)
{
static $memoryCache = [];
$memoryCache[$key] = $data;
return Cache::set($key, $data, $ttl);
}
// 清除缓存
public function clear($key)
{
static $memoryCache = [];
unset($memoryCache[$key]);
return Cache::delete($key);
}
}
2. 数据库查询优化
// 使用索引提示
Db::name('article')
->where('status', 1)
->where('category_id', '>', 0)
->useIndex('idx_status_category')
->select();
// 大数据量分页优化
public function getBigData($lastId = 0, $limit = 100)
{
return Db::name('log')
->where('id', '>', $lastId)
->order('id', 'asc')
->limit($limit)
->select();
}
// 避免N+1查询
$list = Db::name('article')
->with(['user' => function($query) {
$query->field('id,username');
}])
->select();
// 使用游标处理大数据
Db::name('user')->cursor()->each(function($user) {
// 处理每条数据
});
七、项目部署与上线
1. 生产环境配置
// .env.production
APP_DEBUG = false
APP_TRACE = false
DATABASE_HOST = 127.0.0.1
DATABASE_NAME = tp_cms_prod
DATABASE_USER = cms_user
DATABASE_PWD = secure_password
CACHE_TYPE = redis
SESSION_TYPE = redis
# 前端资源CDN配置
RESOURCE_DOMAIN = https://cdn.example.com
# 部署命令
composer install --no-dev --optimize-autoloader
php think optimize:route
php think optimize:schema
2. Nginx配置示例
server {
listen 80;
server_name cms.example.com;
root /var/www/tp-cms/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ .php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /.(?!well-known).* {
deny all;
}
# 静态资源缓存
location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
add_header Cache-Control "public";
}
access_log /var/log/nginx/cms.access.log;
error_log /var/log/nginx/cms.error.log;
}
八、总结与扩展
本教程构建了一个完整的ThinkPHP CMS系统:
- 实现了多模块架构
- 开发了RBAC权限系统
- 构建了内容管理核心
- 优化了系统性能
- 配置了生产环境
扩展方向:
- 多语言支持
- Elasticsearch搜索集成
- 微信小程序对接
- 自动化测试体系
完整项目代码已开源:https://github.com/example/thinkphp-cms