发布日期:2024年1月 | 作者:ThinkPHP高级开发工程师
一、ThinkPHP多应用模式概述
ThinkPHP 6.0+ 引入了全新的多应用模式支持,允许在单一项目中运行多个独立的应用模块。这种架构模式特别适合中大型项目,能够实现业务模块的物理隔离、独立部署和团队协作开发。
多应用模式的核心优势:
- 业务解耦:不同应用模块完全独立,降低耦合度
- 独立部署:支持按应用模块进行独立部署和扩展
- 团队协作:不同团队可以并行开发不同应用模块
- 资源共享:公共组件、模型、服务可以在应用间共享
- 路由隔离:每个应用拥有独立的路由配置和入口
传统单应用 vs 多应用架构对比:
// 传统单应用结构
app/
├── controller/
├── model/
├── view/
└── ...
// 多应用结构
app/
├── admin/ // 后台管理应用
├── api/ // API接口应用
├── web/ // 前台Web应用
└── common/ // 公共应用
二、环境搭建与配置
1. 安装ThinkPHP多应用扩展
// 创建新的ThinkPHP项目
composer create-project topthink/think tp-multi-app
// 进入项目目录
cd tp-multi-app
// 安装多应用模式扩展
composer require topthink/think-multi-app
// 验证安装成功
php think version
2. 基础配置调整
// config/app.php 启用多应用模式
return [
// 开启多应用模式
'auto_multi_app' => true,
// 应用映射(可选)
'app_map' => [
'manage' => 'admin', // manage域名映射到admin应用
],
// 域名绑定(可选)
'domain_bind' => [
'api.example.com' => 'api', // 子域名绑定到api应用
'admin.example.com' => 'admin', // 子域名绑定到admin应用
],
];
3. 目录结构初始化
// 创建基础应用目录结构
php think build admin
php think build api
php think build web
// 生成的目录结构
app/
├── admin/
│ ├── controller/
│ ├── model/
│ ├── view/
│ └── common.php
├── api/
│ ├── controller/
│ ├── model/
│ └── common.php
├── web/
│ ├── controller/
│ ├── model/
│ ├── view/
│ └── common.php
└── common/ // 手动创建公共应用
├── service/
├── middleware/
└── common.php
三、多应用架构实战
1. 应用入口与路由配置
// 应用入口文件 public/admin.php
<?php
namespace think;
require __DIR__ . '/../vendor/autoload.php';
// 执行HTTP应用并响应
$http = (new App())->http;
// 设置应用入口
$response = $http->name('admin')->run();
$response->send();
$http->end($response);
// admin应用路由配置 app/admin/route/app.php
use thinkfacadeRoute;
// 后台管理路由组
Route::group('admin', function () {
// 管理员登录
Route::post('login', 'auth/login');
// 用户管理
Route::get('users', 'user/index');
Route::post('users', 'user/save');
Route::put('users/:id', 'user/update');
Route::delete('users/:id', 'user/delete');
// 角色管理
Route::resource('roles', 'role');
})->middleware(['AdminAuth']);
2. 应用间服务共享
// 公共服务类 app/common/service/UserService.php
namespace appcommonservice;
use thinkfacadeDb;
class UserService
{
/**
* 获取用户信息(跨应用共享)
*/
public static function getUserInfo($userId)
{
return Db::name('user')
->where('id', $userId)
->find();
}
/**
* 更新用户状态
*/
public static function updateUserStatus($userId, $status)
{
return Db::name('user')
->where('id', $userId)
->update(['status' => $status]);
}
}
3. 应用独立中间件
// API应用中间件 app/api/middleware/ApiAuth.php
namespace appapimiddleware;
use thinkfacadeConfig;
class ApiAuth
{
public function handle($request, Closure $next)
{
// API签名验证
$apiKey = $request->header('X-Api-Key');
$timestamp = $request->header('X-Timestamp');
$signature = $request->header('X-Signature');
if (!$this->validateSignature($apiKey, $timestamp, $signature)) {
return json(['code' => 401, 'message' => 'API认证失败']);
}
return $next($request);
}
private function validateSignature($apiKey, $timestamp, $signature)
{
$secret = Config::get('api.secret_key');
$expected = md5($apiKey . $timestamp . $secret);
return $signature === $expected;
}
}
四、高级特性详解
1. 动态应用加载
// 动态应用加载器 app/common/DynamicAppLoader.php
namespace appcommon;
use thinkfacadeConfig;
class DynamicAppLoader
{
/**
* 动态注册应用
*/
public static function registerApps()
{
$apps = self::getAvailableApps();
foreach ($apps as $app) {
if (!in_array($app, Config::get('app.deny_app_list', []))) {
self::loadAppConfig($app);
}
}
}
/**
* 获取可用应用列表
*/
private static function getAvailableApps()
{
$appPath = app()->getAppPath();
$dirs = glob($appPath . '*', GLOB_ONLYDIR);
return array_map('basename', $dirs);
}
/**
* 加载应用配置
*/
private static function loadAppConfig($appName)
{
$configFile = app()->getAppPath() . $appName . '/config/app.php';
if (file_exists($configFile)) {
Config::load($configFile, $appName);
}
}
}
2. 应用事件系统
// 应用事件定义 app/admin/event.php
return [
'bind' => [
'UserLogin' => 'appadmineventUserLogin',
],
'listen' => [
'UserLogin' => ['appadminlistenerLoginLogger'],
'AppInit' => ['appadminlistenerAppInit'],
],
];
// 事件监听器 app/admin/listener/LoginLogger.php
namespace appadminlistener;
use thinkfacadeLog;
class LoginLogger
{
public function handle($event)
{
Log::info("管理员登录: {$event->username} IP: {$event->ip}");
// 记录登录日志到数据库
Db::name('admin_login_log')->insert([
'admin_id' => $event->userId,
'login_ip' => $event->ip,
'login_time' => time()
]);
}
}
3. 数据库连接管理
// 数据库配置 config/database.php
return [
// 默认数据库连接
'default' => env('database.driver', 'mysql'),
// 数据库连接配置
'connections' => [
'mysql' => [
// 主数据库
'type' => 'mysql',
'hostname' => env('database.hostname', '127.0.0.1'),
'database' => env('database.database', 'tp_main'),
'username' => env('database.username', 'root'),
'password' => env('database.password', ''),
// ... 其他配置
],
// 日志数据库(独立连接)
'log_db' => [
'type' => 'mysql',
'hostname' => env('log_db.hostname', '127.0.0.1'),
'database' => env('log_db.database', 'tp_logs'),
'username' => env('log_db.username', 'root'),
'password' => env('log_db.password', ''),
],
],
];
// 在应用中指定数据库连接
namespace appadminmodel;
use thinkModel;
class OperationLog extends Model
{
// 指定连接配置
protected $connection = 'log_db';
}
五、单体应用迁移实战
1. 迁移规划与策略
// 迁移步骤规划
1. 分析现有单体应用结构
2. 识别可拆分的业务模块
3. 设计多应用架构方案
4. 创建新的应用目录结构
5. 逐步迁移控制器、模型等
6. 配置路由和中间件
7. 测试验证功能完整性
8. 部署上线
2. 控制器迁移示例
// 原单体应用控制器 app/controller/User.php
namespace appcontroller;
class User
{
public function index()
{
return '用户列表';
}
public function profile()
{
return '用户详情';
}
}
// 迁移到web应用 app/web/controller/User.php
namespace appwebcontroller;
class User
{
public function index()
{
return '前台用户列表';
}
public function profile()
{
return '前台用户详情';
}
}
// 迁移到admin应用 app/admin/controller/User.php
namespace appadmincontroller;
class User
{
public function index()
{
return '后台用户管理';
}
public function edit()
{
return '编辑用户信息';
}
}
3. 路由迁移配置
// 原单体应用路由 route/app.php
Route::get('user', 'user/index');
Route::get('user/:id', 'user/profile');
Route::get('admin/user', 'admin/user/index');
// 迁移后 - web应用路由 app/web/route/app.php
Route::get('user', 'user/index');
Route::get('user/:id', 'user/profile');
// 迁移后 - admin应用路由 app/admin/route/app.php
Route::get('user', 'user/index');
Route::get('user/edit/:id', 'user/edit');
4. 公共代码提取
// 提取公共模型到common应用
// 原位置: app/model/User.php
// 新位置: app/common/model/User.php
namespace appcommonmodel;
use thinkModel;
class User extends Model
{
// 公共的用户模型逻辑
public function getStatusTextAttr($value, $data)
{
$status = [0 => '禁用', 1 => '正常'];
return $status[$data['status']] ?? '未知';
}
}
// 在各个应用中继承使用
namespace appwebmodel;
use appcommonmodelUser as BaseUser;
class User extends BaseUser
{
// 前台特有的用户模型逻辑
}
六、最佳实践与优化
1. 性能优化策略
// 1. 路由缓存
php think optimize:route
// 2. 配置缓存
php think optimize:config
// 3. 自动加载优化
composer dump-autoload -o
// 4. OPcache配置
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
2. 安全最佳实践
// 1. 应用访问控制
// config/app.php
return [
'deny_app_list' => ['common', 'config'], // 禁止直接访问的应用
// 域名绑定限制
'domain_bind' => [
'admin.domain.com' => 'admin',
'api.domain.com' => 'api',
],
];
// 2. 中间件权限验证
class AdminAuth
{
public function handle($request, Closure $next)
{
if (!session('admin_user')) {
return redirect('/admin/login');
}
// 权限验证逻辑
if (!$this->checkPermission($request)) {
return json(['code' => 403, 'message' => '权限不足']);
}
return $next($request);
}
}
3. 部署与监控
// Nginx多应用配置示例
server {
listen 80;
server_name admin.example.com;
root /path/to/project/public;
index admin.php index.html;
location / {
try_files $uri $uri/ /admin.php?$query_string;
}
location ~ .php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index admin.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
// 应用监控配置
class AppMonitor
{
public static function logPerformance($appName, $executionTime)
{
// 记录应用性能指标
Db::connect('log_db')->name('app_performance')->insert([
'app_name' => $appName,
'execution_time' => $executionTime,
'memory_usage' => memory_get_usage(true),
'create_time' => time()
]);
}
}
4. 团队开发规范
// 团队开发目录结构规范
project/
├── app/
│ ├── admin/ # 后台团队负责
│ ├── api/ # API团队负责
│ ├── web/ # 前端团队负责
│ └── common/ # 架构团队负责
├── config/ # 配置管理
├── database/ # 数据库迁移文件
├── public/ # 静态资源
└── runtime/ # 运行时文件
// Git分支管理策略
main # 主分支
├── develop # 开发分支
│ ├── feature/admin-login # 后台登录功能
│ ├── feature/api-v2 # API v2版本
│ └── feature/web-redesign # 前台重构
└── hotfix # 热修复分支