从零开始构建 ThinkPHP 8 多应用架构的完整指南

ThinkPHP 8 多应用模式完整教程

从零开始构建 ThinkPHP 8 多应用架构的完整指南

📖 目录


1. 什么是多应用模式

1.1 概念说明

多应用模式是指在一个 ThinkPHP 项目中,同时运行多个独立的应用模块,每个应用有自己的控制器、视图、中间件等,但共享模型、服务、配置等资源。

1.2 适用场景

✅ 适合使用多应用模式:

  • 前台 + 后台 + API 三端分离
  • 多个子系统(如:商城、论坛、博客)
  • 不同业务模块需要独立部署
  • 需要不同的访问入口和权限控制

❌ 不适合使用多应用模式:

  • 简单的单一应用
  • 只有一个管理后台
  • 业务逻辑简单,不需要模块化

1.3 多应用 vs 单应用

特性单应用模式多应用模式
目录结构app/controller/app/admin/controller/
app/api/controller/
路由/user/login/admin/user/login
/api/user/login
适用场景小型项目中大型项目
复杂度简单中等
维护性一般

2. 多应用模式安装与配置

2.1 安装多应用扩展

ThinkPHP 8.0 默认是单应用模式,需要安装多应用扩展:

# 1. 创建 ThinkPHP 8 项目composer create-project topthink/think tp8_multi_app # 2. 进入项目目录cd tp8_multi_app # 3. 安装多应用扩展composer require topthink/think-multi-app 

2.2 验证安装

安装成功后,会自动生成多应用支持文件:

# 查看是否安装成功composer show topthink/think-multi-app 

2.3 启用多应用模式

多应用扩展安装后会自动启用,无需额外配置。


3. 目录结构规划

3.1 标准目录结构

project/ ├── app/ # 应用目录 │ ├── common/ # 公共模块 ⭐ │ │ ├── model/ # 共享模型 │ │ │ ├── User.php │ │ │ ├── Article.php │ │ │ └── Category.php │ │ ├── service/ # 共享服务 │ │ │ ├── UserService.php │ │ │ ├── SmsService.php │ │ │ └── UploadService.php │ │ ├── library/ # 共享类库 │ │ │ ├── Auth.php │ │ │ └── Tree.php │ │ ├── validate/ # 共享验证器 │ │ │ └── UserValidate.php │ │ └── exception/ # 共享异常类 │ │ └── ApiException.php │ │ │ ├── admin/ # 后台应用 ⭐ │ │ ├── controller/ # 控制器 │ │ │ ├── Index.php │ │ │ ├── User.php │ │ │ └── Article.php │ │ ├── service/ # 后台专属服务 │ │ │ ├── AdminService.php │ │ │ └── MenuService.php │ │ ├── middleware/ # 后台中间件 │ │ │ └── AdminAuth.php │ │ ├── view/ # 后台视图 │ │ │ ├── index/ │ │ │ └── user/ │ │ ├── config/ # 后台配置(可选) │ │ │ └── app.php │ │ ├── route/ # 后台路由 │ │ │ └── app.php │ │ ├── event.php # 后台事件定义 │ │ ├── middleware.php # 后台中间件定义 │ │ └── provider.php # 后台服务提供者 │ │ │ ├── api/ # API 应用 ⭐ │ │ ├── controller/ │ │ │ ├── Index.php │ │ │ ├── User.php │ │ │ └── Article.php │ │ ├── service/ # API 专属服务 │ │ │ └── TokenService.php │ │ ├── middleware/ # API 中间件 │ │ │ ├── JwtAuth.php │ │ │ └── Cors.php │ │ ├── route/ # API 路由 │ │ │ └── app.php │ │ ├── event.php │ │ ├── middleware.php │ │ └── provider.php │ │ │ ├── index/ # 前台应用 ⭐ │ │ ├── controller/ │ │ │ ├── Index.php │ │ │ └── Article.php │ │ ├── service/ # 前台专属服务 │ │ │ ├── CartService.php │ │ │ └── OrderService.php │ │ ├── middleware/ │ │ │ └── UserAuth.php │ │ ├── view/ # 前台视图 │ │ ├── route/ │ │ │ └── app.php │ │ ├── event.php │ │ ├── middleware.php │ │ └── provider.php │ │ │ ├── event.php # 全局事件定义 │ ├── middleware.php # 全局中间件定义 │ ├── provider.php # 全局服务提供者 │ ├── ExceptionHandle.php # 全局异常处理 │ └── Request.php # 全局请求类 │ ├── config/ # 全局配置目录 │ ├── app.php # 应用配置 │ ├── cache.php # 缓存配置 │ ├── database.php # 数据库配置 │ ├── route.php # 路由配置 │ └── view.php # 视图配置 │ ├── public/ # 公共资源目录 │ ├── index.php # 入口文件 │ ├── static/ # 静态资源 │ │ ├── admin/ # 后台静态资源 │ │ ├── api/ # API 文档等 │ │ └── index/ # 前台静态资源 │ └── storage/ # 上传文件 │ ├── runtime/ # 运行时目录 │ ├── admin/ # 后台运行时 │ ├── api/ # API 运行时 │ └── index/ # 前台运行时 │ ├── route/ # 全局路由目录 │ └── app.php │ ├── .env # 环境变量 ├── composer.json └── think # 命令行工具 

3.2 创建应用目录

方式 1:手动创建

# 创建后台应用mkdir -p app/admin/controller mkdir -p app/admin/service mkdir -p app/admin/middleware mkdir -p app/admin/view # 创建 API 应用mkdir -p app/api/controller mkdir -p app/api/service mkdir -p app/api/middleware # 创建前台应用mkdir -p app/index/controller mkdir -p app/index/service mkdir -p app/index/middleware mkdir -p app/index/view # 创建公共模块mkdir -p app/common/model mkdir -p app/common/service mkdir -p app/common/library mkdir -p app/common/validate 

方式 2:使用命令行(推荐)

# ThinkPHP 8 提供了命令行工具 php think build 

3.3 目录说明

目录说明共享性
app/common/公共模块,所有应用共享✅ 共享
app/admin/后台应用,独立的业务逻辑❌ 独立
app/api/API 应用,提供接口服务❌ 独立
app/index/前台应用,面向用户❌ 独立
config/全局配置,所有应用共享✅ 共享
route/全局路由配置✅ 共享

4. 路由配置

4.1 多应用路由规则

多应用模式下,URL 访问规则为:

http://domain.com/应用名/控制器/操作/参数 

示例:

http://example.com/admin/user/index # 后台用户列表 http://example.com/api/user/login # API 用户登录 http://example.com/index/article/detail # 前台文章详情 

4.2 全局路由配置

文件:config/route.php

<?phpreturn[// 是否强制使用路由'url_route_must'=>false,// 路由使用完整匹配'route_complete_match'=>false,// 是否开启路由解析缓存'route_check_cache'=>false,// 路由缓存连接名称'route_cache_option'=>[],// 默认应用'default_app'=>'index',// 应用映射(可选)'app_map'=>[// 'admin' => 'backend', // 将 admin 映射为 backend],// 域名绑定(可选)'domain_bind'=>[// 'admin.example.com' => 'admin',// 'api.example.com' => 'api',],// 禁止访问的应用'deny_app_list'=>['common'],];

4.3 应用独立路由

后台路由:app/admin/route/app.php

<?phpusethink\facade\Route;// 后台首页Route::get('/','index/index');// 后台登录Route::get('login','login/index');Route::post('login','login/check');Route::get('logout','login/logout');// 用户管理(资源路由)Route::resource('user','user');// 文章管理Route::group('article',function(){Route::get('/','article/index');Route::get('create','article/create');Route::post('save','article/save');Route::get('edit/<id>','article/edit');Route::put('update/<id>','article/update');Route::delete('delete/<id>','article/delete');});// 需要登录的路由组Route::group(function(){Route::get('dashboard','index/dashboard');Route::get('profile','user/profile');})->middleware(\app\admin\middleware\AdminAuth::class);

API 路由:app/api/route/app.php

<?phpusethink\facade\Route;// API 版本 1Route::group('v1',function(){// 用户相关Route::post('login','user/login');Route::post('register','user/register');// 需要认证的接口Route::group(function(){Route::get('user/info','user/info');Route::put('user/update','user/update');Route::get('article/list','article/list');})->middleware(\app\api\middleware\JwtAuth::class);});// API 版本 2Route::group('v2',function(){Route::post('login','v2.user/login');Route::get('article/list','v2.article/list');});// 跨域中间件(所有 API 路由)Route::middleware(\app\api\middleware\Cors::class);

前台路由:app/index/route/app.php

<?phpusethink\facade\Route;// 首页Route::get('/','index/index');// 文章Route::get('article/<id>','article/detail');Route::get('article/category/<cate_id>','article/category');// 用户中心(需要登录)Route::group('user',function(){Route::get('profile','user/profile');Route::get('orders','order/list');Route::get('order/<id>','order/detail');})->middleware(\app\index\middleware\UserAuth::class);

4.4 域名绑定

如果不同应用使用不同域名,可以配置域名绑定:

文件:config/route.php

<?phpreturn[// 域名绑定'domain_bind'=>['admin.example.com'=>'admin',// 后台域名'api.example.com'=>'api',// API 域名'www.example.com'=>'index',// 前台域名],];

访问示例:

http://admin.example.com/user/index # 等同于 /admin/user/index http://api.example.com/user/login # 等同于 /api/user/login http://www.example.com/article/detail # 等同于 /index/article/detail 

4.5 路由别名

文件:config/route.php

<?phpreturn[// 应用映射'app_map'=>['backend'=>'admin',// 访问 /backend 实际访问 admin 应用'mobile'=>'index',// 访问 /mobile 实际访问 index 应用],];

5. 服务层架构

5.1 服务层概念

服务层(Service Layer)是业务逻辑的核心,位于控制器和模型之间,负责处理复杂的业务逻辑。

架构层次:

Controller (控制器) ↓ 调用 Service (服务层) ↓ 调用 Model (模型层) ↓ 操作 Database (数据库) 

5.2 共享服务(app/common/service/)

用户服务:app/common/service/UserService.php

<?phpdeclare(strict_types=1);namespaceapp\common\service;useapp\common\model\User;usethink\facade\Cache;/** * 用户服务(所有应用共享) */classUserService{/** * 获取用户信息(带缓存) */publicfunctiongetUserInfo(int$userId):array{$cacheKey='user_info_'.$userId;returnCache::remember($cacheKey,function()use($userId){$user=User::find($userId);return$user?$user->toArray():[];},3600);}/** * 更新用户信息 */publicfunctionupdateUser(int$userId,array$data):bool{$user=User::find($userId);if(!$user){thrownew\Exception('用户不存在');}$result=$user->save($data);// 清除缓存Cache::delete('user_info_'.$userId);return$result!==false;}/** * 检查用户名是否存在 */publicfunctioncheckUsername(string$username):bool{returnUser::where('username',$username)->count()>0;}}

短信服务:app/common/service/SmsService.php

<?phpdeclare(strict_types=1);namespaceapp\common\service;usethink\facade\Cache;/** * 短信服务(所有应用共享) */classSmsService{/** * 发送验证码 */publicfunctionsendCode(string$mobile,string$scene='login'):bool{// 生成验证码$code=$this->generateCode();// 发送短信(这里使用阿里云短信服务示例)$result=$this->sendSms($mobile,$code);if($result){// 缓存验证码(5分钟有效)$cacheKey='sms_code_'.$scene.'_'.$mobile;Cache::set($cacheKey,$code,300);returntrue;}returnfalse;}/** * 验证验证码 */publicfunctionverifyCode(string$mobile,string$code,string$scene='login'):bool{$cacheKey='sms_code_'.$scene.'_'.$mobile;$cachedCode=Cache::get($cacheKey);if($cachedCode&&$cachedCode===$code){// 验证成功后删除缓存Cache::delete($cacheKey);returntrue;}returnfalse;}/** * 生成验证码 */privatefunctiongenerateCode(int$length=6):string{returnstr_pad((string)mt_rand(0,pow(10,$length)-1),$length,'0',STR_PAD_LEFT);}/** * 发送短信(示例) */privatefunctionsendSms(string$mobile,string$code):bool{// 这里接入实际的短信服务商 API// 例如:阿里云、腾讯云等returntrue;}}

5.3 应用专属服务

后台管理员服务:app/admin/service/AdminService.php

<?phpdeclare(strict_types=1);namespaceapp\admin\service;useapp\common\model\Admin;usethink\facade\Session;classAdminService{publicfunctionlogin(string$username,string$password):array{$admin=Admin::where('username',$username)->find();if(!$admin||!password_verify($password,$admin->password)){thrownew\Exception('用户名或密码错误');}Session::set('admin_id',$admin->id);Session::set('admin_name',$admin->username);return$admin->toArray();}}

API Token 服务:app/api/service/TokenService.php

<?phpdeclare(strict_types=1);namespaceapp\api\service;useFirebase\JWT\JWT;useFirebase\JWT\Key;classTokenService{privatestring$key='your-secret-key';publicfunctioncreateToken(array$data):string{$payload=['iat'=>time(),'exp'=>time()+7200,'data'=>$data];returnJWT::encode($payload,$this->key,'HS256');}publicfunctionverifyToken(string$token):array{try{$decoded=JWT::decode($token,newKey($this->key,'HS256'));return(array)$decoded->data;}catch(\Exception$e){thrownew\Exception('Token 无效',401);}}}

6. 模型层共享

6.1 模型放置位置

所有模型统一放在 app/common/model/ 目录,供所有应用共享。

6.2 用户模型示例

文件:app/common/model/User.php

<?phpdeclare(strict_types=1);namespaceapp\common\model;usethink\Model;usethink\model\concern\SoftDelete;classUserextendsModel{useSoftDelete;protected$name='user';protectedstring$deleteTime='delete_time';protected$autoWriteTimestamp=true;protected$type=['id'=>'integer','status'=>'integer',];protected$hidden=['password','delete_time'];publicfunctionsetPasswordAttr($value):string{returnpassword_hash($value,PASSWORD_DEFAULT);}}

6.3 文章模型示例

文件:app/common/model/Article.php

<?phpdeclare(strict_types=1);namespaceapp\common\model;usethink\Model;classArticleextendsModel{protected$name='article';protected$autoWriteTimestamp=true;// 关联分类publicfunctioncategory(){return$this->belongsTo(Category::class,'cate_id');}// 关联作者publicfunctionauthor(){return$this->belongsTo(User::class,'user_id');}}

7. 缓存配置

7.1 统一缓存配置

文件:config/cache.php

<?phpreturn['default'=>'redis','stores'=>['file'=>['type'=>'file','path'=>runtime_path().'cache/','expire'=>0,],'redis'=>['type'=>'redis','host'=>env('redis.host','127.0.0.1'),'port'=>env('redis.port',6379),'password'=>env('redis.password',''),'select'=>0,'prefix'=>'myapp:',],],];

7.2 缓存服务封装

文件:app/common/service/CacheService.php

<?phpdeclare(strict_types=1);namespaceapp\common\service;usethink\facade\Cache;classCacheService{// 设置应用缓存(自动添加应用前缀)publicstaticfunctionsetAppCache(string$key,$value,int$expire=0):bool{$appName=app('http')->getName();$cacheKey=$appName.':'.$key;returnCache::set($cacheKey,$value,$expire);}// 获取应用缓存publicstaticfunctiongetAppCache(string$key){$appName=app('http')->getName();$cacheKey=$appName.':'.$key;returnCache::get($cacheKey);}// 设置共享缓存publicstaticfunctionsetCommonCache(string$key,$value,int$expire=0):bool{returnCache::set('common:'.$key,$value,$expire);}// 获取共享缓存publicstaticfunctiongetCommonCache(string$key){returnCache::get('common:'.$key);}}

8. 中间件配置

8.1 全局中间件

文件:app/middleware.php

<?php// 全局中间件定义(所有应用都会执行)return[// 跨域请求支持\think\middleware\AllowCrossDomain::class,// Session 初始化\think\middleware\SessionInit::class,];

8.2 应用中间件

后台中间件:app/admin/middleware.php

<?phpreturn[// 后台认证中间件\app\admin\middleware\AdminAuth::class,];

API 中间件:app/api/middleware.php

<?phpreturn[// JWT 认证中间件\app\api\middleware\JwtAuth::class,// 跨域中间件\app\api\middleware\Cors::class,];

8.3 后台认证中间件

文件:app/admin/middleware/AdminAuth.php

<?phpdeclare(strict_types=1);namespaceapp\admin\middleware;usethink\facade\Session;classAdminAuth{publicfunctionhandle($request,\Closure$next){// 白名单(不需要登录的页面)$whitelist=['login/index','login/check'];$controller=$request->controller();$action=$request->action();$path=$controller.'/'.$action;// 检查是否在白名单中if(in_array($path,$whitelist)){return$next($request);}// 检查是否登录if(!Session::has('admin_id')){returnredirect('/admin/login');}return$next($request);}}

8.4 JWT 认证中间件

文件:app/api/middleware/JwtAuth.php

<?phpdeclare(strict_types=1);namespaceapp\api\middleware;useapp\api\service\TokenService;classJwtAuth{publicfunctionhandle($request,\Closure$next){$token=$request->header('Authorization');if(empty($token)){returnjson(['code'=>401,'msg'=>'未登录']);}// 移除 "Bearer " 前缀$token=str_replace('Bearer ','',$token);$tokenService=newTokenService();try{$userData=$tokenService->verifyToken($token);$request->userData=$userData;}catch(\Exception$e){returnjson(['code'=>401,'msg'=>$e->getMessage()]);}return$next($request);}}

8.5 跨域中间件

文件:app/api/middleware/Cors.php

<?phpdeclare(strict_types=1);namespaceapp\api\middleware;classCors{publicfunctionhandle($request,\Closure$next){header('Access-Control-Allow-Origin: *');header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');header('Access-Control-Allow-Headers: Authorization, Content-Type');// OPTIONS 请求直接返回if($request->method()=='OPTIONS'){returnresponse('',200);}return$next($request);}}

9. 异常处理

9.1 全局异常处理

文件:app/ExceptionHandle.php

<?phpdeclare(strict_types=1);namespaceapp;usethink\db\exception\DataNotFoundException;usethink\db\exception\ModelNotFoundException;usethink\exception\Handle;usethink\exception\HttpException;usethink\exception\ValidateException;usethink\Response;useThrowable;classExceptionHandleextendsHandle{publicfunctionrender($request,Throwable$e):Response{// 验证异常if($einstanceofValidateException){returnjson(['code'=>1,'msg'=>$e->getError()]);}// 数据不存在异常if($einstanceofDataNotFoundException||$einstanceofModelNotFoundException){returnjson(['code'=>404,'msg'=>'数据不存在']);}// HTTP 异常if($einstanceofHttpException){returnjson(['code'=>$e->getStatusCode(),'msg'=>$e->getMessage()]);}// 其他异常returnjson(['code'=>500,'msg'=>$e->getMessage(),'file'=>$e->getFile(),'line'=>$e->getLine(),]);}}

9.2 自定义异常类

文件:app/common/exception/ApiException.php

<?phpdeclare(strict_types=1);namespaceapp\common\exception;useException;classApiExceptionextendsException{publicfunction__construct(string$message='',int$code=400){parent::__construct($message,$code);}}

9.3 使用自定义异常

<?phpnamespaceapp\api\controller;useapp\common\exception\ApiException;classUser{publicfunctioninfo(){$user=User::find(1);if(!$user){thrownewApiException('用户不存在',404);}returnjson(['code'=>0,'data'=>$user]);}}

10. 数据库配置

10.1 统一数据库配置

文件:config/database.php

<?phpreturn['default'=>env('database.driver','mysql'),'connections'=>['mysql'=>['type'=>'mysql','hostname'=>env('database.hostname','127.0.0.1'),'database'=>env('database.database','test'),'username'=>env('database.username','root'),'password'=>env('database.password',''),'hostport'=>env('database.hostport','3306'),'charset'=>'utf8mb4','prefix'=>env('database.prefix',''),],],];

10.2 环境变量配置

文件:.env

[DATABASE] TYPE = mysql HOSTNAME = 127.0.0.1 DATABASE = myapp USERNAME = root PASSWORD = 123456 HOSTPORT = 3306 PREFIX = tp_ 

10.3 多数据库连接

如果不同应用需要连接不同数据库:

<?phpreturn['default'=>'mysql','connections'=>['mysql'=>['type'=>'mysql','hostname'=>'127.0.0.1','database'=>'main_db','username'=>'root','password'=>'',],'mysql_admin'=>['type'=>'mysql','hostname'=>'127.0.0.1','database'=>'admin_db','username'=>'root','password'=>'',],],];

使用示例:

<?php// 使用默认连接$user=User::find(1);// 使用指定连接$admin=Admin::connect('mysql_admin')->find(1);

11. 视图配置

11.1 统一视图配置

文件:config/view.php

<?phpreturn['type'=>'Think','view_path'=>'','view_suffix'=>'html','view_depr'=>DIRECTORY_SEPARATOR,'tpl_begin'=>'{','tpl_end'=>'}','taglib_begin'=>'{','taglib_end'=>'}',];

11.2 应用视图目录

app/ ├── admin/ │ └── view/ │ ├── index/ │ │ └── index.html │ └── user/ │ ├── index.html │ └── edit.html │ └── index/ └── view/ ├── index/ │ └── index.html └── article/ └── detail.html 

11.3 控制器中使用视图

后台控制器:app/admin/controller/Index.php

<?phpnamespaceapp\admin\controller;useapp\BaseController;classIndexextendsBaseController{publicfunctionindex(){// 渲染视图:app/admin/view/index/index.htmlreturnview('index',['title'=>'后台首页','user'=>session('admin_name'),]);}}

11.4 视图模板示例

文件:app/admin/view/index/index.html

<!DOCTYPEhtml><html><head><title>{$title}</title></head><body><h1>欢迎,{$user}</h1><p>这是后台首页</p></body></html>

12. 公共类库

12.1 公共类库目录

app/common/library/ ├── Auth.php # 权限认证类 ├── Tree.php # 树形结构类 ├── Upload.php # 上传类 └── Wechat.php # 微信类 

12.2 权限认证类示例

文件:app/common/library/Auth.php

<?phpdeclare(strict_types=1);namespaceapp\common\library;usethink\facade\Session;classAuth{/** * 检查权限 */publicstaticfunctioncheck(string$rule):bool{$adminId=Session::get('admin_id');if(!$adminId){returnfalse;}// 超级管理员if($adminId==1){returntrue;}// 检查权限逻辑// ...returntrue;}}

12.3 树形结构类示例

文件:app/common/library/Tree.php

<?phpdeclare(strict_types=1);namespaceapp\common\library;classTree{/** * 生成树形结构 */publicstaticfunctiontoTree(array$list,int$pid=0,string$pidField='pid'):array{$tree=[];foreach($listas$item){if($item[$pidField]==$pid){$children=self::toTree($list,$item['id'],$pidField);if($children){$item['children']=$children;}$tree[]=$item;}}return$tree;}}

13. 事件系统

13.1 全局事件定义

文件:app/event.php

<?phpreturn['bind'=>[],'listen'=>['AppInit'=>[],'HttpRun'=>[],'HttpEnd'=>[],'LogWrite'=>[],],'subscribe'=>[],];

13.2 应用事件定义

后台事件:app/admin/event.php

<?phpreturn['bind'=>[],'listen'=>['AdminLogin'=>[\app\admin\listener\AdminLoginListener::class,],],'subscribe'=>[],];

13.3 事件类

文件:app/admin/event/AdminLogin.php

<?phpdeclare(strict_types=1);namespaceapp\admin\event;classAdminLogin{public$admin;publicfunction__construct($admin){$this->admin=$admin;}}

13.4 监听器类

文件:app/admin/listener/AdminLoginListener.php

<?phpdeclare(strict_types=1);namespaceapp\admin\listener;useapp\admin\event\AdminLogin;classAdminLoginListener{publicfunctionhandle(AdminLogin$event){// 记录登录日志$admin=$event->admin;// 写入日志// ...}}

13.5 触发事件

<?phpnamespaceapp\admin\controller;useapp\admin\event\AdminLogin;classLogin{publicfunctioncheck(){// 登录逻辑$admin=['id'=>1,'username'=>'admin'];// 触发事件event(newAdminLogin($admin));returnjson(['code'=>0,'msg'=>'登录成功']);}}

14. 验证器共享

14.1 验证器目录

app/common/validate/ ├── UserValidate.php ├── ArticleValidate.php └── LoginValidate.php 

14.2 用户验证器

文件:app/common/validate/UserValidate.php

<?phpdeclare(strict_types=1);namespaceapp\common\validate;usethink\Validate;classUserValidateextendsValidate{protected$rule=['username'=>'require|length:3,20|alphaNum','password'=>'require|length:6,20','email'=>'require|email','mobile'=>'require|mobile',];protected$message=['username.require'=>'用户名不能为空','username.length'=>'用户名长度为3-20个字符','username.alphaNum'=>'用户名只能是字母和数字','password.require'=>'密码不能为空','password.length'=>'密码长度为6-20个字符','email.require'=>'邮箱不能为空','email.email'=>'邮箱格式不正确','mobile.require'=>'手机号不能为空','mobile.mobile'=>'手机号格式不正确',];protected$scene=['login'=>['username','password'],'register'=>['username','password','email','mobile'],'edit'=>['email','mobile'],];}

14.3 在控制器中使用验证器

后台控制器:app/admin/controller/User.php

<?phpnamespaceapp\admin\controller;useapp\common\validate\UserValidate;usethink\Request;classUser{publicfunctionsave(Request$request){$data=$request->post();// 验证数据$validate=newUserValidate();if(!$validate->scene('register')->check($data)){returnjson(['code'=>1,'msg'=>$validate->getError()]);}// 保存数据// ...returnjson(['code'=>0,'msg'=>'保存成功']);}}

API 控制器:app/api/controller/User.php

<?phpnamespaceapp\api\controller;useapp\common\validate\UserValidate;usethink\Request;classUser{publicfunctionregister(Request$request){$data=$request->post();// 使用相同的验证器$validate=newUserValidate();if(!$validate->scene('register')->check($data)){returnjson(['code'=>1,'msg'=>$validate->getError()]);}// 注册逻辑// ...returnjson(['code'=>0,'msg'=>'注册成功']);}}

15. 跨应用调用

15.1 跨应用调用服务

场景:API 应用需要调用后台应用的服务

<?phpnamespaceapp\api\controller;useapp\admin\service\AdminService;// 调用后台服务classAdmin{publicfunctionlogin(){// 可以直接调用其他应用的服务$adminService=newAdminService();$result=$adminService->login('admin','123456');returnjson(['code'=>0,'data'=>$result]);}}

15.2 跨应用调用模型

所有应用共享模型,无需跨应用调用

<?php// 后台应用namespaceapp\admin\controller;useapp\common\model\User;classUser{publicfunctionindex(){$list=User::select();returnjson(['code'=>0,'data'=>$list]);}}
<?php// API 应用namespaceapp\api\controller;useapp\common\model\User;// 使用相同的模型classUser{publicfunctionlist(){$list=User::select();returnjson(['code'=>0,'data'=>$list]);}}

15.3 注意事项

⚠️ 跨应用调用要谨慎:

  • 避免循环依赖
  • 如果多个应用都需要,考虑将服务移到 common
  • 注意命名空间的正确引用

16. 最佳实践

16.1 目录组织原则

✅ 推荐做法:

1. 共享资源放在 common - 模型(Model) - 通用服务(Service) - 公共类库(Library) - 验证器(Validate) 2. 应用专属资源放在各应用目录 - 控制器(Controller) - 应用专属服务(Service) - 中间件(Middleware) - 视图(View) 3. 配置文件统一放在 config - 数据库配置 - 缓存配置 - 路由配置 

16.2 命名规范

控制器命名:

// ✅ 正确 app/admin/controller/User.php app/api/controller/User.php // ❌ 错误 app/admin/controller/user.php app/api/controller/UserController.php 

服务命名:

// ✅ 正确 app/common/service/UserService.php app/admin/service/AdminService.php // ❌ 错误 app/common/service/User.php app/admin/service/Admin.php 

16.3 代码复用

✅ 推荐:使用服务层复用业务逻辑

<?php// 共享服务namespaceapp\common\service;classUserService{publicfunctiongetUserInfo(int$userId):array{// 业务逻辑return[];}}// 后台控制器namespaceapp\admin\controller;classUser{publicfunctioninfo(){$service=new\app\common\service\UserService();returnjson($service->getUserInfo(1));}}// API 控制器namespaceapp\api\controller;classUser{publicfunctioninfo(){$service=new\app\common\service\UserService();returnjson($service->getUserInfo(1));}}

16.4 依赖注入

✅ 推荐:使用依赖注入

<?phpnamespaceapp\admin\controller;useapp\common\service\UserService;classUser{protectedUserService$userService;// 构造函数注入publicfunction__construct(UserService$userService){$this->userService=$userService;}publicfunctioninfo(){returnjson($this->userService->getUserInfo(1));}}

16.5 缓存策略

✅ 推荐:使用 Redis + 缓存前缀

<?php// 共享缓存(所有应用可访问)Cache::set('common:user_info_1',$data);// 应用专属缓存(带应用前缀)$appName=app('http')->getName();Cache::set($appName.':user_list',$data);

16.6 路由规划

✅ 推荐:使用资源路由

<?php// app/admin/route/app.phpusethink\facade\Route;// 资源路由Route::resource('user','user');// 等同于:// GET /user -> user/index// GET /user/create -> user/create// POST /user -> user/save// GET /user/:id -> user/read// GET /user/:id/edit -> user/edit// PUT /user/:id -> user/update// DELETE /user/:id -> user/delete

17. 常见问题

17.1 如何访问多应用?

问题: 安装多应用扩展后,如何访问不同的应用?

解决方案:

# 访问后台应用 http://example.com/admin/user/index # 访问 API 应用 http://example.com/api/user/login # 访问前台应用 http://example.com/index/article/detail 

17.2 如何设置默认应用?

问题: 访问根目录时,默认进入哪个应用?

解决方案:

文件:config/route.php

<?phpreturn[// 设置默认应用为 index'default_app'=>'index',];

访问 http://example.com/ 会自动进入 index 应用。

17.3 如何禁止访问某个应用?

问题: 不想让用户直接访问 common 应用

解决方案:

文件:config/route.php

<?phpreturn[// 禁止访问的应用列表'deny_app_list'=>['common'],];

17.4 多应用如何共享 Session?

问题: 后台登录后,API 应用无法获取 Session

解决方案:

Session 默认是共享的,确保以下配置:

文件:config/session.php

<?phpreturn['type'=>'file','prefix'=>'think',// 统一前缀'expire'=>3600,];

17.5 如何实现应用间数据隔离?

问题: 不同应用需要使用不同的数据表前缀

解决方案:

方式 1:使用不同的数据库连接

<?php// config/database.phpreturn['connections'=>['mysql'=>['prefix'=>'admin_',],'mysql_api'=>['prefix'=>'api_',],],];// 使用Admin::connect('mysql')->select();// 使用 admin_ 前缀User::connect('mysql_api')->select();// 使用 api_ 前缀

方式 2:在模型中指定前缀

<?phpnamespaceapp\common\model;classAdminextendsModel{protected$connection='mysql';protected$table='admin_user';// 完整表名}

17.6 如何实现应用独立配置?

问题: 不同应用需要不同的配置

解决方案:

创建应用配置文件:app/admin/config/app.php

<?phpreturn['app_name'=>'后台管理系统','page_size'=>20,];

使用应用配置:

<?php// 获取应用配置$appName=config('app.app_name');// 获取全局配置$debug=config('app.debug');

17.7 如何实现域名绑定?

问题: 不同应用使用不同域名访问

解决方案:

文件:config/route.php

<?phpreturn['domain_bind'=>['admin.example.com'=>'admin','api.example.com'=>'api','www.example.com'=>'index',],];

Nginx 配置:

server { listen 80; server_name admin.example.com api.example.com www.example.com; root /path/to/project/public; index index.php; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } 

17.8 如何调试多应用?

问题: 如何查看当前是哪个应用?

解决方案:

<?php// 获取当前应用名称$appName=app('http')->getName();echo$appName;// 输出:admin、api、index// 获取当前控制器$controller=request()->controller();// 获取当前操作$action=request()->action();

17.9 多应用如何部署?

问题: 生产环境如何部署多应用?

解决方案:

# 1. 关闭调试模式# .env APP_DEBUG =false# 2. 优化自动加载composerinstall --optimize-autoloader --no-dev # 3. 缓存配置 php think optimize:config # 4. 缓存路由 php think optimize:route # 5. 设置目录权限chmod -R 755 /path/to/project chmod -R 777 runtime chmod -R 777 public/storage 

17.10 如何创建新应用?

问题: 如何快速创建一个新应用?

解决方案:

# 1. 创建应用目录mkdir -p app/shop/controller mkdir -p app/shop/service mkdir -p app/shop/middleware mkdir -p app/shop/view # 2. 创建控制器# app/shop/controller/Index.php<?php namespace app\shop\controller; class Index { public functionindex(){return'Shop Application';}}# 3. 访问新应用 http://example.com/shop/index/index 

18. 完整实战案例

18.1 项目需求

构建一个包含以下功能的多应用系统:

  • 后台应用(admin):管理员登录、用户管理、文章管理
  • API 应用(api):提供 RESTful API 接口
  • 前台应用(index):用户浏览文章

18.2 项目结构

project/ ├── app/ │ ├── common/ │ │ ├── model/ │ │ │ ├── User.php │ │ │ └── Article.php │ │ └── service/ │ │ └── UserService.php │ ├── admin/ │ │ ├── controller/ │ │ │ ├── Login.php │ │ │ ├── User.php │ │ │ └── Article.php │ │ ├── middleware/ │ │ │ └── AdminAuth.php │ │ └── route/ │ │ └── app.php │ ├── api/ │ │ ├── controller/ │ │ │ ├── User.php │ │ │ └── Article.php │ │ ├── middleware/ │ │ │ └── JwtAuth.php │ │ └── route/ │ │ └── app.php │ └── index/ │ ├── controller/ │ │ ├── Index.php │ │ └── Article.php │ └── route/ │ └── app.php └── config/ ├── app.php ├── database.php └── cache.php 

18.3 后台登录实现

控制器:app/admin/controller/Login.php

<?phpdeclare(strict_types=1);namespaceapp\admin\controller;useapp\admin\service\AdminService;usethink\Request;classLogin{protectedAdminService$adminService;publicfunction__construct(AdminService$adminService){$this->adminService=$adminService;}// 登录页面publicfunctionindex(){returnview('login/index');}// 登录验证publicfunctioncheck(Request$request){$username=$request->post('username');$password=$request->post('password');try{$admin=$this->adminService->login($username,$password);returnjson(['code'=>0,'msg'=>'登录成功','data'=>$admin]);}catch(\Exception$e){returnjson(['code'=>1,'msg'=>$e->getMessage()]);}}// 退出登录publicfunctionlogout(){$this->adminService->logout();returnredirect('/admin/login');}}

18.4 API 接口实现

控制器:app/api/controller/Article.php

<?phpdeclare(strict_types=1);namespaceapp\api\controller;useapp\common\model\Article;usethink\Request;classArticle{// 文章列表publicfunctionlist(Request$request){$page=$request->param('page',1,'intval');$limit=$request->param('limit',10,'intval');$list=Article::where('status',1)->with('category')->order('id','desc')->page($page,$limit)->select();$total=Article::where('status',1)->count();returnjson(['code'=>0,'msg'=>'success','data'=>['list'=>$list,'total'=>$total,'page'=>$page,'limit'=>$limit,]]);}// 文章详情publicfunctiondetail(Request$request){$id=$request->param('id',0,'intval');$article=Article::with('category')->find($id);if(!$article){returnjson(['code'=>404,'msg'=>'文章不存在']);}returnjson(['code'=>0,'msg'=>'success','data'=>$article]);}}

18.5 前台展示实现

控制器:app/index/controller/Article.php

<?phpdeclare(strict_types=1);namespaceapp\index\controller;useapp\common\model\Article;usethink\Request;classArticle{// 文章详情页publicfunctiondetail(Request$request){$id=$request->param('id',0,'intval');$article=Article::with('category')->find($id);if(!$article){abort(404,'文章不存在');}// 增加浏览量$article->inc('views')->update();returnview('article/detail',['article'=>$article,]);}}

19. 性能优化建议

19.1 缓存优化

<?php// 1. 使用 Redis 缓存// config/cache.phpreturn['default'=>'redis',];// 2. 缓存查询结果$list=Article::cache('article_list',3600)->select();// 3. 使用标签缓存Cache::tag('article')->set('list',$data);Cache::tag('article')->clear();// 清除所有文章相关缓存

19.2 数据库优化

<?php// 1. 只查询需要的字段$list=Article::field('id,title,create_time')->select();// 2. 使用预加载避免 N+1 问题$list=Article::with('category')->select();// 3. 使用索引// 确保 where 条件的字段有索引

19.3 路由优化

# 缓存路由 php think optimize:route # 缓存配置 php think optimize:config 

20. 安全建议

20.1 SQL 注入防护

<?php// ✅ 正确:使用参数绑定$list=Db::name('user')->where('id',$id)->select();// ❌ 错误:直接拼接 SQL$sql="SELECT * FROM user WHERE202_XSS__2286">20.2 XSS 防护<?php// 模板中自动转义{$content}// 自动转义// 不转义(危险){$content|raw}20.3 CSRF 防护<?php// 开启 CSRF 验证// config/middleware.phpreturn[\think\middleware\FormTokenCheck::class,];21. 总结21.1 多应用模式核心要点要点说明目录结构清晰的应用划分,common 存放共享资源路由配置每个应用独立路由,支持域名绑定服务层共享服务放 common,专属服务放各应用模型层统一放在 common/model,所有应用共享缓存配置使用 Redis 统一缓存,支持应用前缀中间件全局中间件 + 应用中间件事件系统全局事件 + 应用事件21.2 开发流程1. 安装多应用扩展 ↓ 2. 规划目录结构 ↓ 3. 创建应用目录 ↓ 4. 配置路由 ↓ 5. 开发控制器 ↓ 6. 开发服务层 ↓ 7. 开发模型层 ↓ 8. 配置中间件 ↓ 9. 测试部署 21.3 学习路径初级:理解多应用概念掌握目录结构学会基本路由配置实现简单的 CRUD中级:掌握服务层设计理解依赖注入学会中间件使用掌握缓存策略高级:事件系统应用性能优化安全防护分布式部署22. 参考资源22.1 官方文档ThinkPHP 8 官方文档: https://doc.thinkphp.cn/v8_0/多应用扩展: https://github.com/top-think/think-multi-appGitHub: https://github.com/top-think/think22.2 相关教程TP8常见问题FAQ.mdthinkphp行为文档.md22.3 社区资源ThinkPHP 社区: https://www.kancloud.cn/thinkphp问答社区: https://www.thinkphp.cn/ask23. 快速参考23.1 常用命令# 安装多应用扩展composer require topthink/think-multi-app # 创建控制器 php think make:controller admin@User # 创建模型 php think make:model common@User # 创建中间件 php think make:middleware admin@AdminAuth # 缓存路由 php think optimize:route # 缓存配置 php think optimize:config # 清除缓存 php think clear23.2 常用配置<?php// 设置默认应用'default_app'=>'index',// 禁止访问的应用'deny_app_list'=>['common'],// 域名绑定'domain_bind'=>['admin.example.com'=>'admin',],// 应用映射'app_map'=>['backend'=>'admin',],23.3 目录速查app/common/ # 共享资源 ├── model/ # 模型 ├── service/ # 服务 ├── library/ # 类库 ├── validate/ # 验证器 └── exception/ # 异常类 app/admin/ # 后台应用 ├── controller/ # 控制器 ├── service/ # 服务 ├── middleware/ # 中间件 ├── view/ # 视图 └── route/ # 路由 app/api/ # API 应用 ├── controller/ ├── service/ ├── middleware/ └── route/ app/index/ # 前台应用 ├── controller/ ├── service/ ├── middleware/ ├── view/ └── route/ 24. 附录24.1 完整的 composer.json{"name":"topthink/think","type":"project","require":{"php":">=8.0","topthink/framework":"^8.0","topthink/think-orm":"^3.0","topthink/think-multi-app":"^1.0","topthink/think-view":"^1.0","firebase/php-jwt":"^6.0"},"autoload":{"psr-4":{"app\\":"app/"}}}24.2 完整的 .env 示例APP_DEBUG = true APP_TRACE = false [APP] DEFAULT_TIMEZONE = Asia/Shanghai [DATABASE] TYPE = mysql HOSTNAME = 127.0.0.1 DATABASE = myapp USERNAME = root PASSWORD = 123456 HOSTPORT = 3306 CHARSET = utf8mb4 PREFIX = tp_ [REDIS] HOST = 127.0.0.1 PORT = 6379 PASSWORD = SELECT = 0 [CACHE] DRIVER = redis PREFIX = myapp: 🎉 恭喜!您已完成 ThinkPHP 8 多应用模式完整教程的学习!如有问题,请参考:TP8常见问题FAQ.md官方文档 

Read more

Flutter for OpenHarmony:data_assets — 资源映射与自动装配实践(适配鸿蒙 HarmonyOS Next ohos)

Flutter for OpenHarmony:data_assets — 资源映射与自动装配实践(适配鸿蒙 HarmonyOS Next ohos)

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net。 前言 在大型鸿蒙(OpenHarmony)工程中,手动管理静态资源路径极其容易出错。data_assets 提供了一套严谨的代码生成方案,能自动扫描资源并将其转换为强类型的 Dart 类,从根本上消灭了资源引用的运行时错误。 一、核心价值 1.1 基础概念 data_assets 的核心是资源到代码的静态映射。 引用 Assets.homeIcon 编译期校验路径 导致 assets/data: JSON, PNG, SVG DataAssets 生成器 assets.dart: 强类型索引类 鸿蒙业务逻辑 错误的文件名 编译失败提示 1.2 进阶概念 * Type Safety (类型安全):将字符串路径转化为

By Ne0inhk

Ubuntu24.04.3——ROS2一键安装

这篇文章在开局需要叠个甲,这片文章基本上是摘自于B站up鱼香ROS机器人的动手学ROS2文章(链接:动手学ROS2),如有侵权,请联系我删除,相关视频参考【鱼香ROS】动手学ROS2|ROS2基础入门到实践教程|小鱼带你手把手学习ROS2_哔哩哔哩_bilibili 一、一键安装ROS2 首先启动虚拟机或者启动双系统中的ubuntu,打开终端(快捷键Alt+Ctrl+T) 输入下面的指令 wget http://fishros.com/install -O fishros && . fishros 输入密码 在选项界面选择1-一键安装 注意这里的24.=版本的ubuntu只有jazzy和rolling版本,我选的是jazzy版本,选什么版本会导致之后你的终端命令的一些代码会有改动。 出现如图所示,即ROS2安装完成 2.出现问题可以这样卸载 sudo apt remove ros-jazzy-* sudo apt autoremove 3.ROS2到底装哪里了

By Ne0inhk
ubuntu24.04+5090显卡驱动安装踩坑

ubuntu24.04+5090显卡驱动安装踩坑

⭐安装ubuntu24.04 在选择进入 try or install ubuntu 之后会出现持续黑屏现象, 卡在了 booting a command list 解决方案: 选中 try or install ubuntu  按键盘 "e" 进入编辑模式 找到下列位置并添加  nomodeset acpi=off noapic 参数 按下 键盘F10,就可以正常安装 ubuntu 24.04系统了 ⭐安装显卡驱动前置条件 第一步 升级内核 uname -a 查看内核版本 安装5090显卡 必须要将内核版本升级到 6.13 ,用`mainline`工具安装 1.

By Ne0inhk
Flutter 组件 heart 适配鸿蒙 HarmonyOS 实战:分布式心跳监控,构建全场景保活检测与链路哨兵架构

Flutter 组件 heart 适配鸿蒙 HarmonyOS 实战:分布式心跳监控,构建全场景保活检测与链路哨兵架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 heart 适配鸿蒙 HarmonyOS 实战:分布式心跳监控,构建全场景保活检测与链路哨兵架构 前言 在鸿蒙(OpenHarmony)生态迈向万物智联、涉及海量传感器节点通信、分布式长连接保活及实时状态同步的背景下,如何确保终端设备在弱网、休眠或异常断电场景下仍能被母座感知,已成为决定系统可用性的“生命信标”。在鸿蒙设备这类强调分布式软总线协同与严苛电源管理的环境下,如果应用依然依赖基础的 HTTP 定时轮询执行状态探测,由于由于 CPU 频繁唤醒带来的功耗负担及无状态协议的连接开销,极易由于由于心跳风暴导致设备续航崩穿或大规模误判掉线。 我们需要一种能够实现毫秒级超时检测、支持异步回调闭环且具备高性能状态机控制的心跳监控方案。 heart 为 Flutter 开发者引入了轻量级且工业标准的“心搏”治理范式。它通过对 Ping-Pong 交互的时序解构,将复杂的超时重试与状态翻转逻辑封装为声明式的配置。在适配到鸿蒙 HarmonyO

By Ne0inhk