多应用架构
最后更新: 2026-01-27 11:02:47多应用架构
Unicode Framework 支持多应用架构,允许在单个项目中运行多个独立的应用程序。这对于需要同时提供 Web 前端、管理后台、API 服务等的项目非常有用。
概述
多应用架构允许您在一个框架实例中运行多个应用,每个应用有自己独立的:
- 控制器
- 模型
- 路由
- 配置
- 视图
应用目录结构
app/
├── index/ # 默认应用(Web 前端)
│ ├── config/
│ ├── controller/
│ ├── model/
│ ├── view/
│ └── route.php
├── admin/ # 管理后台应用
│ ├── config/
│ ├── controller/
│ ├── model/
│ └── route.php
└── api/ # API 应用
├── config/
├── controller/
├── model/
└── route.php
应用结构
标准应用目录
每个应用应包含以下目录和文件:
app/{app-name}/
├── config/ # 应用配置(可选)
│ └── app.php
├── controller/ # 控制器
│ └── Index.php
├── model/ # 模型(可选)
│ └── User.php
├── view/ # 视图(可选)
│ └── index/
│ └── index.tpl
└── route.php # 应用路由
命名空间规范
应用的命名空间遵循以下规则:
// 控制器命名空间
App\{AppName}\Controller\{ControllerName}
// 示例
App\Index\Controller\UserController
App\Admin\Controller\UserController
App\Api\Controller\UserController
// 模型命名空间
App\{AppName}\Model\{ModelName}
// 示例
App\Index\Model\User
App\Admin\Model\User
路由策略
框架支持三种路由策略来区分不同的应用:
1. 路径策略(Path Strategy)
通过 URL 路径前缀区分应用。
配置 (config/app.php):
return [
'multi_app' => [
'enabled' => true,
'resolution_strategy' => 'path', // 路径策略
],
];
路由示例:
// app/index/route.php
Route::get('/users', [UserController::class, 'index']);
// 访问:/index/users
// app/admin/route.php
Route::get('/users', [UserController::class, 'index']);
// 访问:/admin/users
// app/api/route.php
Route::get('/users', [UserController::class, 'index']);
// 访问:/api/users
默认应用:
// config/app.php
return [
'default_app' => 'index',
// ...
];
// 访问根路径 / 会自动路由到 index 应用
Route::get('/', [IndexController::class, 'index']);
// 访问:/
2. 域名策略(Domain Strategy)
通过域名区分应用。
配置:return [
'multi_app' => [
'enabled' => true,
'resolution_strategy' => 'domain',
'domain_mapping' => [
'www.example.com' => 'index',
'admin.example.com' => 'admin',
'api.example.com' => 'api',
],
],
];
路由示例:
// app/index/route.php
Route::get('/users', [UserController::class, 'index']);
// 访问:www.example.com/users
// app/admin/route.php
Route::get('/users', [UserController::class, 'index']);
// 访问:admin.example.com/users
3. 子域名策略(Subdomain Strategy)
通过子域名区分应用(自动从子域名提取应用名)。
配置:return [
'multi_app' => [
'enabled' => true,
'resolution_strategy' => 'subdomain',
],
];
路由示例:
// 子域名 admin.example.com 自动映射到 app/admin
// 子域名 api.example.com 自动映射到 app/api
应用配置
全局配置
在 config/app.php 中配置多应用相关设置:
return [
// 默认应用
'default_app' => 'index',
// 默认控制器
'default_controller' => 'Index',
// 默认方法
'default_action' => 'index',
// 多应用配置
'multi_app' => [
'enabled' => true,
'resolution_strategy' => 'path', // path, domain, subdomain
'domain_mapping' => [
// 域名策略时使用
],
],
];
应用级配置
每个应用可以有自己独立的配置文件 app/{app-name}/config/app.php:
// app/admin/config/app.php
return [
'name' => 'Admin Panel',
'default_controller' => 'Dashboard',
'default_action' => 'index',
];
应用级配置会覆盖全局配置。
应用上下文
框架提供了 AppContext 类来管理当前应用上下文。
获取当前应用信息
use Unicode\Framework\MultiApp\AppContext;
// 获取当前应用名称
$appName = AppContext::getAppName(); // 'index', 'admin', 'api'
// 获取当前应用路径
$appPath = AppContext::getAppPath(); // '/path/to/app/index'
// 获取路由前缀
$prefix = AppContext::getRoutePrefix(); // '/index', '/admin', '/api'
// 检查是否有应用上下文
if (AppContext::hasApp()) {
// 当前在多应用模式下
}
在控制器中使用
namespace App\Index\Controller;
use Unicode\Framework\Http\Request;
use Unicode\Framework\MultiApp\AppContext;
class IndexController
{
public function index(Request $request): array
{
return [
'app_name' => AppContext::getAppName(),
'app_path' => AppContext::getAppPath(),
];
}
}
路由定义
框架级路由
在项目根目录的 route.php 中定义的路由对所有应用都有效:
// route.php
use Unicode\Framework\Route\Route;
// 健康检查(所有应用共享)
Route::get('/health', function() {
return ['status' => 'ok'];
}, 'framework.health');
应用级路由
在 app/{app-name}/route.php 中定义的路由只对该应用有效:
// app/index/route.php
use Unicode\Framework\Route\Route;
Route::get('/users', [UserController::class, 'index'], 'index.users.index');
路由优先级
应用级路由优先于框架级路由。如果路径冲突,应用级路由会覆盖框架级路由。
控制器开发
控制器命名
// app/index/controller/UserController.php
namespace App\Index\Controller;
use Unicode\Framework\Http\Request;
class UserController
{
public function index(Request $request): array
{
return ['users' => []];
}
}
跨应用调用
不同应用之间的控制器是独立的,不能直接调用。如果需要共享逻辑,应该:
// src/Service/UserService.php
namespace App\Service;
class UserService
{
public function getAllUsers(): array
{
// 共享的业务逻辑
}
}
// 在各个应用的控制器中使用
use App\Service\UserService;
class UserController
{
public function index(Request $request): array
{
$service = new UserService();
return ['users' => $service->getAllUsers()];
}
}
// app/index/model/User.php 和 app/admin/model/User.php
// 可以共享同一个模型类,或者继承基础模型
最佳实践
1. 应用职责划分
// index 应用:面向用户的 Web 前端
app/index/
├── controller/
│ ├── HomeController.php
│ ├── ProductController.php
│ └── CartController.php
└── route.php
// admin 应用:管理后台
app/admin/
├── controller/
│ ├── DashboardController.php
│ ├── UserManageController.php
│ └── ProductManageController.php
└── route.php
// api 应用:RESTful API
app/api/
├── controller/
│ ├── UserController.php
│ └── ProductController.php
└── route.php
2. 共享资源
对于需要在多个应用间共享的资源:
src/Model/ 或各应用独立src/Service/src/Utils/src/Middleware/3. 配置管理
// 全局配置:config/app.php
// 应用配置:app/{app-name}/config/app.php
// 读取配置
config('app.name'); // 全局配置
config('app.name', null, 'admin'); // 应用配置(如果支持)
4. 路由组织
// app/index/route.php - Web 前端路由
Route::get('/', [HomeController::class, 'index']);
Route::get('/products', [ProductController::class, 'index']);
// app/admin/route.php - 管理后台路由
Route::middleware([AdminAuthMiddleware::class], function() {
Route::get('/dashboard', [DashboardController::class, 'index']);
Route::get('/users', [UserManageController::class, 'index']);
});
// app/api/route.php - API 路由
Route::group('/api/v1', function() {
Route::get('/users', [UserController::class, 'index']);
Route::post('/users', [UserController::class, 'store']);
});
5. 环境区分
// 开发环境:所有应用都可用
// 生产环境:可以禁用某些应用
// config/app.php
return [
'multi_app' => [
'enabled' => true,
'available_apps' => ['index', 'api'], // 只启用部分应用
],
];
常见问题
Q: 如何在不同应用间共享数据?
A: 使用数据库、缓存或共享服务类。不同应用是独立的,不能直接共享内存数据。
Q: 应用之间可以互相调用控制器吗?
A: 不建议。应该通过服务类或模型来共享逻辑。
Q: 如何为不同应用配置不同的中间件?
A: 在各自应用的 route.php 中定义中间件。
Q: 默认应用如何配置?
A: 在 config/app.php 中设置 default_app,访问根路径 / 时会路由到默认应用。
Q: 路由缓存对多应用有效吗?
A: 是的。路由缓存会包含所有应用的路由,在生产环境下自动启用。