去年接手了一个图书销售平台的重构项目,客户要求同时支持ThinkPHP和Laravel双框架运行环境。这个55ap4swk项目本质上是一个全功能的B2C图书电商系统,需要处理日均5万PV的访问量。系统包含前端商品展示、会员中心、购物流程,以及后台的进销存管理、订单处理等核心模块。
选择双框架方案主要基于两点考虑:一是客户原有团队熟悉ThinkPHP但需要向Laravel技术栈迁移;二是需要验证不同框架在高并发电商场景下的性能表现。实际开发中,我们采用了抽象层设计,使业务逻辑代码能兼容两种框架,仅基础设施层需要分别实现。
系统采用经典的三层架构,但针对双框架需求做了特殊设计:
code复制表现层
├── ThinkPHP路由适配器
├── Laravel路由适配器
├── 统一模板引擎(Twig)
业务逻辑层
├── 领域服务(订单/支付/库存)
├── 应用服务(购物车/搜索)
数据访问层
├── ThinkPHP模型适配器
├── Laravel Eloquent适配器
├── 统一查询构造器
通过依赖注入容器动态加载框架特定的实现类。例如订单创建服务:
php复制interface OrderCreatorInterface {
public function create(OrderDTO $dto);
}
// ThinkPHP实现
class ThinkOrderCreator implements OrderCreatorInterface {
public function create(OrderDTO $dto) {
// 使用TP的Db类操作
}
}
// Laravel实现
class LaravelOrderCreator implements OrderCreatorInterface {
public function create(OrderDTO $dto) {
// 使用Eloquent操作
}
}
图书电商的数据库设计有几个关键点需要特别注意:
sql复制CREATE TABLE `book_skus` (
`id` bigint(20) UNSIGNED NOT NULL,
`book_id` bigint(20) NOT NULL COMMENT '主商品ID',
`attributes` json NOT NULL COMMENT '规格属性{版本:精装,开本:16开}',
`price` decimal(10,2) NOT NULL,
`stock` int(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
订单分表策略:
按用户ID哈希分10个表,解决订单数据膨胀问题。我们编写了统一的分表查询组件,自动路由到正确的物理表。
搜索优化:
除了常规的Elasticsearch集成外,针对图书特点增加了:
图书促销时面临的超卖问题,我们实现了三级库存校验:
php复制$redis->eval(
"if tonumber(redis.call('get', KEYS[1])) >= tonumber(ARGV[1]) then
return redis.call('decrby', KEYS[1], ARGV[1])
else
return -1
end",
1, 'stock:book_123', 1
);
重要提示:Redis库存需要设置过期时间(通常2小时),避免异常订单占用库存。我们曾因未设置过期导致库存冻结,教训深刻。
支付流程的异常处理是电商系统的难点之一。我们的状态机设计如下:
mermaid复制stateDiagram-v2
[*] --> 待支付
待支付 --> 支付中 : 发起支付
支付中 --> 支付成功 : 回调验证通过
支付中 --> 支付失败 : 明确失败
支付中 --> 待确认 : 未收到回调
待确认 --> 支付成功 : 人工核查
待确认 --> 已取消 : 超时未处理
针对微信和支付宝的不同特性,我们抽象出统一的支付网关接口:
php复制interface PaymentGateway {
public function prepare(array $order): PaymentPrepareResponse;
public function verify(string $notifyData): bool;
public function query(string $tradeNo): PaymentQueryResult;
}
实际开发中发现支付宝的异步通知可能有10分钟延迟,而微信通常在2秒内到达。这要求超时检查策略需要区别处理。
商品详情页采用三级缓存策略:
Nginx配置示例:
nginx复制location /book/ {
try_files /cache/$uri.html @php;
# 静态文件设置强缓存
expires 1h;
add_header Cache-Control "public";
}
location @php {
# 动态请求设置协商缓存
add_header Cache-Control "no-cache";
fastcgi_pass php-fpm;
}
在相同硬件环境下(4核8G)压测结果:
| 场景 | ThinkPHP6 QPS | Laravel8 QPS |
|---|---|---|
| 商品列表(无缓存) | 328 | 421 |
| 订单创建 | 156 | 203 |
| 搜索查询 | 287 | 362 |
Laravel在ORM性能上优势明显,特别是关联查询场景。但ThinkPHP的内存占用更低,适合资源受限环境。
使用Docker构建多阶段镜像,通过环境变量切换框架:
dockerfile复制# 基础镜像
FROM php:8.1-fpm AS base
RUN apt-get update && apt-get install -y \
libzip-dev \
&& docker-php-ext-install zip pdo_mysql
# Laravel镜像
FROM base AS laravel
COPY --from=composer /usr/bin/composer /usr/bin/composer
COPY . /var/www
RUN composer install --optimize-autoloader --no-dev
# ThinkPHP镜像
FROM base AS thinkphp
COPY . /var/www
RUN chmod -R 755 /var/www/runtime
通过Kubernetes ConfigMap控制启动参数:
yaml复制apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: web
image: "${IMAGE}"
env:
- name: FRAMEWORK
valueFrom:
configMapKeyRef:
name: app-config
key: framework.type
我们重点监控以下自定义指标:
使用Prometheus收集的示例查询:
promql复制# 库存操作失败率
sum(rate(stock_operation_failed_total[5m])) by (method)
/
sum(rate(stock_operation_total[5m])) by (method)
跨框架开发的坑:
图书类目特殊处理:
性能优化真言:
这个项目让我深刻体会到,框架只是工具,良好的架构设计才是系统健壮性的根本。特别是在双框架环境下,合理的抽象层能大幅降低维护成本。建议在类似项目中尽早建立契约测试,确保不同实现的行为一致性。