ThinkPHP多应用模式的优势
ThinkPHP 6.x引入了多应用模式,允许在一个项目中创建多个独立的应用模块,如API接口、后台管理系统、微信小程序接口等。这种架构模式提高了代码的可维护性,实现了业务逻辑的清晰分离,是现代Web开发的首选方案。
环境准备与项目创建
1. 环境要求与安装
确保系统满足以下要求:PHP >= 7.2.5,Composer,MySQL 5.7+
# 通过Composer创建ThinkPHP项目
composer create-project topthink/think tp6-multi-app
# 进入项目目录
cd tp6-multi-app
# 安装多应用模式扩展
composer require topthink/think-multi-app
# 启动内置服务器进行测试
php think run
2. 多应用模式配置
修改config/app.php配置文件,开启多应用模式:
// config/app.php
return [
// 开启多应用模式
'auto_multi_app' => true,
'app_express' => true,
// 默认应用
'default_app' => 'index',
// 应用映射(域名绑定应用)
'app_map' => [
'api' => 'api', // api.domain.com → api应用
'admin' => 'admin', // admin.domain.com → admin应用
],
// 域名绑定
'domain_bind' => [],
];
实战案例:构建多应用电商系统
我们将创建一个包含API应用和后台管理应用的电商系统,实现商品管理、用户管理和订单管理功能。
1. 创建应用结构
# 创建API应用
php think build api
# 创建后台管理应用
php think build admin
# 创建公共函数文件
# app/common.php 放置跨应用共享函数
2. 数据库设计与模型创建
创建商品表、用户表和订单表:
// 数据库迁移文件 database/migrations/202308010001_create_tables.php
<?php
use thinkmigrationMigrator;
class CreateTables extends Migrator
{
public function change()
{
// 用户表
$table = $this->table('users', ['comment' => '用户表']);
$table->addColumn('username', 'string', ['limit' => 50, 'comment' => '用户名'])
->addColumn('email', 'string', ['limit' => 100, 'comment' => '邮箱'])
->addColumn('password', 'string', ['limit' => 255, 'comment' => '密码'])
->addColumn('create_time', 'datetime')
->addColumn('update_time', 'datetime')
->addIndex(['username'], ['unique' => true])
->addIndex(['email'], ['unique' => true])
->create();
// 商品表
$table = $this->table('products', ['comment' => '商品表']);
$table->addColumn('name', 'string', ['limit' => 100, 'comment' => '商品名称'])
->addColumn('price', 'decimal', ['precision' => 10, 'scale' => 2, 'comment' => '价格'])
->addColumn('stock', 'integer', ['comment' => '库存'])
->addColumn('description', 'text', ['comment' => '商品描述'])
->addColumn('status', 'integer', ['default' => 1, 'comment' => '状态:1上架,0下架'])
->addColumn('create_time', 'datetime')
->addColumn('update_time', 'datetime')
->create();
// 订单表
$table = $this->table('orders', ['comment' => '订单表']);
$table->addColumn('user_id', 'integer', ['comment' => '用户ID'])
->addColumn('order_sn', 'string', ['limit' => 50, 'comment' => '订单号'])
->addColumn('total_amount', 'decimal', ['precision' => 10, 'scale' => 2, 'comment' => '订单金额'])
->addColumn('status', 'integer', ['default' => 0, 'comment' => '订单状态'])
->addColumn('create_time', 'datetime')
->addColumn('update_time', 'datetime')
->addIndex(['order_sn'], ['unique' => true])
->addIndex(['user_id'])
->create();
// 订单商品表
$table = $this->table('order_items', ['comment' => '订单商品表']);
$table->addColumn('order_id', 'integer', ['comment' => '订单ID'])
->addColumn('product_id', 'integer', ['comment' => '商品ID'])
->addColumn('quantity', 'integer', ['comment' => '数量'])
->addColumn('price', 'decimal', ['precision' => 10, 'scale' => 2, 'comment' => '单价'])
->addColumn('create_time', 'datetime')
->addIndex(['order_id'])
->addIndex(['product_id'])
->create();
}
}
3. API应用开发
创建商品API控制器,实现RESTful接口:
// app/api/controller/ProductController.php
<?php
namespace appapicontroller;
use thinkApp;
use thinkfacadeRequest;
use appcommonmodelProduct as ProductModel;
use appcommontraitsApiResponse;
class ProductController
{
use ApiResponse;
protected $productModel;
public function __construct(App $app, ProductModel $productModel)
{
$this->productModel = $productModel;
}
/**
* 商品列表
*/
public function index()
{
try {
$page = Request::param('page', 1);
$limit = Request::param('limit', 10);
$keyword = Request::param('keyword', '');
$where = [['status', '=', 1]];
if (!empty($keyword)) {
$where[] = ['name', 'like', "%{$keyword}%"];
}
$list = $this->productModel->where($where)
->field('id,name,price,stock,description')
->paginate(['page' => $page, 'list_rows' => $limit]);
return $this->success('获取成功', $list);
} catch (Exception $e) {
return $this->error('获取失败: ' . $e->getMessage());
}
}
/**
* 商品详情
*/
public function read($id)
{
try {
$product = $this->productModel->where('id', $id)
->where('status', 1)
->field('id,name,price,stock,description,create_time')
->find();
if (!$product) {
return $this->error('商品不存在');
}
return $this->success('获取成功', $product);
} catch (Exception $e) {
return $this->error('获取失败: ' . $e->getMessage());
}
}
/**
* 创建订单
*/
public function createOrder()
{
try {
$productId = Request::param('product_id');
$quantity = Request::param('quantity', 1);
$userId = Request::param('user_id'); // 实际应从token获取
// 验证参数
if (!$productId || $quantity error('参数错误');
}
// 调用订单服务创建订单
$orderService = new appcommonserviceOrderService();
$result = $orderService->createOrder($userId, $productId, $quantity);
if ($result['code'] === 0) {
return $this->success('订单创建成功', $result['data']);
} else {
return $this->error($result['msg']);
}
} catch (Exception $e) {
return $this->error('创建订单失败: ' . $e->getMessage());
}
}
}
4. 后台管理应用开发
创建商品管理控制器:
// app/admin/controller/ProductController.php
<?php
namespace appadmincontroller;
use thinkfacadeRequest;
use thinkfacadeView;
use appcommonmodelProduct as ProductModel;
use appcommontraitsAdminResponse;
class ProductController
{
use AdminResponse;
protected $productModel;
public function __construct(ProductModel $productModel)
{
$this->productModel = $productModel;
}
/**
* 商品管理页面
*/
public function index()
{
return View::fetch('product/index');
}
/**
* 获取商品列表数据
*/
public function getList()
{
try {
$page = Request::param('page', 1);
$limit = Request::param('limit', 10);
$keyword = Request::param('keyword', '');
$status = Request::param('status', '');
$where = [];
if (!empty($keyword)) {
$where[] = ['name', 'like', "%{$keyword}%"];
}
if ($status !== '') {
$where[] = ['status', '=', $status];
}
$list = $this->productModel->where($where)
->order('create_time', 'desc')
->paginate(['page' => $page, 'list_rows' => $limit]);
return $this->success('获取成功', [
'list' => $list->items(),
'total' => $list->total()
]);
} catch (Exception $e) {
return $this->error('获取失败: ' . $e->getMessage());
}
}
/**
* 添加商品
*/
public function add()
{
if (Request::isPost()) {
try {
$data = Request::post();
// 验证数据
$validate = new appadminvalidateProduct();
if (!$validate->check($data)) {
return $this->error($validate->getError());
}
$result = $this->productModel->save($data);
if ($result) {
return $this->success('添加成功');
} else {
return $this->error('添加失败');
}
} catch (Exception $e) {
return $this->error('添加失败: ' . $e->getMessage());
}
}
return View::fetch('product/add');
}
/**
* 编辑商品
*/
public function edit($id)
{
$product = $this->productModel->find($id);
if (!$product) {
return $this->error('商品不存在');
}
if (Request::isPost()) {
try {
$data = Request::post();
// 验证数据
$validate = new appadminvalidateProduct();
if (!$validate->scene('edit')->check($data)) {
return $this->error($validate->getError());
}
$product->save($data);
return $this->success('更新成功');
} catch (Exception $e) {
return $this->error('更新失败: ' . $e->getMessage());
}
}
View::assign('product', $product);
return View::fetch('product/edit');
}
}
5. 公共模型与服务
创建商品模型和订单服务:
// app/common/model/Product.php
<?php
namespace appcommonmodel;
use thinkModel;
class Product extends Model
{
// 设置表名
protected $name = 'products';
// 自动时间戳
protected $autoWriteTimestamp = true;
protected $createTime = 'create_time';
protected $updateTime = 'update_time';
// 字段自动完成
protected $insert = ['status' => 1];
/**
* 减少库存
*/
public function decreaseStock($id, $quantity)
{
$product = $this->find($id);
if (!$product) {
throw new Exception('商品不存在');
}
if ($product->stock where('id', $id)
->dec('stock', $quantity)
->update();
}
}
// app/common/service/OrderService.php
<?php
namespace appcommonservice;
use thinkfacadeDb;
use appcommonmodelOrder;
use appcommonmodelProduct;
use thinkfacadeLog;
class OrderService
{
/**
* 创建订单
*/
public function createOrder($userId, $productId, $quantity)
{
Db::startTrans();
try {
// 获取商品信息
$productModel = new Product();
$product = $productModel->where('id', $productId)
->where('status', 1)
->lock(true)
->find();
if (!$product) {
throw new Exception('商品不存在或已下架');
}
if ($product->stock generateOrderSn();
// 计算总金额
$totalAmount = bcmul($product->price, $quantity, 2);
// 创建订单
$orderData = [
'user_id' => $userId,
'order_sn' => $orderSn,
'total_amount' => $totalAmount,
'status' => 0 // 待支付
];
$order = new Order();
$order->save($orderData);
// 创建订单商品
$orderItemData = [
'order_id' => $order->id,
'product_id' => $productId,
'quantity' => $quantity,
'price' => $product->price
];
Db::name('order_items')->insert($orderItemData);
// 减少库存
$productModel->decreaseStock($productId, $quantity);
Db::commit();
return [
'code' => 0,
'msg' => '创建成功',
'data' => [
'order_id' => $order->id,
'order_sn' => $orderSn,
'total_amount' => $totalAmount
]
];
} catch (Exception $e) {
Db::rollback();
Log::error('创建订单失败: ' . $e->getMessage());
return [
'code' => 1,
'msg' => $e->getMessage()
];
}
}
/**
* 生成唯一订单号
*/
private function generateOrderSn()
{
return date('YmdHis') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
}
}
路由配置与API文档
1. API路由配置
// app/api/route/app.php
<?php
use thinkfacadeRoute;
// 商品路由
Route::get('products', 'ProductController/index');
Route::get('products/:id', 'ProductController/read');
Route::post('orders', 'ProductController/createOrder');
// 用户路由
Route::post('login', 'UserController/login');
Route::post('register', 'UserController/register');
Route::get('userinfo', 'UserController/userInfo')->middleware('Auth');
2. 后台路由配置
// app/admin/route/app.php
<?php
use thinkfacadeRoute;
// 商品管理路由
Route::get('products', 'ProductController/index');
Route::get('products/list', 'ProductController/getList');
Route::get('products/add', 'ProductController/add');
Route::post('products/add', 'ProductController/add');
Route::get('products/edit/:id', 'ProductController/edit');
Route::post('products/edit/:id', 'ProductController/edit');
// 需要权限的路由
Route::group(function() {
Route::get('users', 'UserController/index');
Route::get('orders', 'OrderController/index');
})->middleware('AdminAuth');
3. 中间件开发
创建API认证中间件:
// app/api/middleware/Auth.php
<?php
namespace appapimiddleware;
use thinkfacadeRequest;
use thinkfacadeResponse;
use appcommonserviceJwtService;
class Auth
{
public function handle($request, Closure $next)
{
$token = Request::header('Authorization');
if (!$token) {
return Response::create(['code' => 401, 'msg' => 'Token缺失'], 'json');
}
try {
$jwtService = new JwtService();
$payload = $jwtService->verifyToken($token);
// 将用户信息存入请求对象
$request->user = $payload['user'];
return $next($request);
} catch (Exception $e) {
return Response::create(['code' => 401, 'msg' => 'Token无效'], 'json');
}
}
}
部署与优化建议
1. 生产环境部署
# 优化配置缓存
php think optimize:config
# 路由缓存
php think optimize:route
# 关闭调试模式
# .env 文件中设置 APP_DEBUG = false
# 配置Nginx
server {
listen 80;
server_name yourdomain.com;
root /path/to/tp6-multi-app/public;
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=$1 last;
break;
}
}
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;
}
}
2. 性能优化建议
- 使用OPcache加速PHP执行
- 配置Redis缓存会话和常用数据
- 启用数据库查询缓存
- 使用CDN加速静态资源
- 定期清理日志文件和缓存文件
总结
ThinkPHP 6.x的多应用模式为现代Web开发提供了强大的架构支持。通过本文的实战案例,我们展示了如何构建一个完整的电商系统,包含API接口和后台管理功能。
关键要点:
- 合理规划应用结构,分离API和后台功能
- 使用模型和服务层处理业务逻辑
- 实现完善的错误处理和日志记录
- 使用中间件进行身份验证和权限控制
- 数据库事务确保数据一致性
通过掌握ThinkPHP的多应用开发,您可以构建出结构清晰、易于维护的高质量Web应用程序。