发布日期:2024年1月20日
一、项目架构设计
本教程将使用PHP8开发一个完整的电商订单微服务API,包含以下核心模块:
- 认证服务:JWT身份验证与权限控制
- 订单服务:订单CRUD与状态管理
- 支付服务:集成第三方支付接口
- 日志服务:请求监控与异常追踪
- 缓存服务:Redis性能优化
技术栈:PHP8.2 + Slim Framework + Doctrine ORM + PHPUnit
二、环境配置与初始化
1. 项目创建与依赖安装
composer create-project slim/slim-skeleton order-api
cd order-api
composer require doctrine/orm league/oauth2-server firebase/php-jwt predis/predis monolog/monolog
2. 目录结构设计
src/
├── Core/ # 核心组件
│ ├── Database.php # 数据库连接
│ ├── Logger.php # 日志系统
│ └── Router.php # 路由扩展
├── Entities/ # 数据实体
├── Services/ # 业务服务
├── Middlewares/ # 中间件
├── Controllers/ # 控制器
├── Repositories/ # 数据仓库
├── Tests/ # 单元测试
config/
├── routes.php # 路由配置
├── dependencies.php # 依赖注入
public/
├── index.php # 入口文件
三、核心功能实现
1. JWT认证服务
// src/Services/AuthService.php
namespace AppServices;
use FirebaseJWTJWT;
use FirebaseJWTKey;
class AuthService {
private $secretKey;
private $algorithm = 'HS256';
public function __construct(string $secretKey) {
$this->secretKey = $secretKey;
}
public function generateToken(array $user): string {
$payload = [
'iss' => 'order-api',
'sub' => $user['id'],
'name' => $user['name'],
'roles' => $user['roles'],
'iat' => time(),
'exp' => time() + 3600 // 1小时过期
];
return JWT::encode($payload, $this->secretKey, $this->algorithm);
}
public function validateToken(string $token): ?array {
try {
$decoded = JWT::decode($token, new Key($this->secretKey, $this->algorithm));
return (array)$decoded;
} catch (Exception $e) {
return null;
}
}
}
2. 认证中间件
// src/Middlewares/AuthMiddleware.php
namespace AppMiddlewares;
use PsrHttpMessageServerRequestInterface as Request;
use PsrHttpServerRequestHandlerInterface as Handler;
class AuthMiddleware {
private $authService;
public function __construct(AuthService $authService) {
$this->authService = $authService;
}
public function __invoke(Request $request, Handler $handler) {
$token = $this->extractToken($request);
if (!$token || !($payload = $this->authService->validateToken($token))) {
return new Response(401, ['Content-Type' => 'application/json'],
json_encode(['error' => 'Unauthorized']));
}
// 将用户信息添加到请求属性
$request = $request->withAttribute('user', $payload);
return $handler->handle($request);
}
private function extractToken(Request $request): ?string {
$header = $request->getHeaderLine('Authorization');
if (preg_match('/Bearers(S+)/', $header, $matches)) {
return $matches[1];
}
return null;
}
}
四、订单服务开发
1. 订单实体设计
// src/Entities/Order.php
namespace AppEntities;
use DoctrineORMMapping as ORM;
#[ORMEntity]
#[ORMTable(name: 'orders')]
class Order {
#[ORMId]
#[ORMGeneratedValue]
#[ORMColumn(type: 'integer')]
private $id;
#[ORMColumn(type: 'string', length: 50)]
private $orderNumber;
#[ORMColumn(type: 'decimal', precision: 10, scale: 2)]
private $totalAmount;
#[ORMColumn(type: 'string', length: 20)]
private $status;
#[ORMColumn(type: 'datetime')]
private $createdAt;
#[ORMManyToOne(targetEntity: 'User')]
private $user;
// Getters和Setters方法...
}
2. 订单控制器
// src/Controllers/OrderController.php
namespace AppControllers;
use AppRepositoriesOrderRepository;
use PsrHttpMessageResponseInterface as Response;
use PsrHttpMessageServerRequestInterface as Request;
class OrderController {
private $orderRepository;
public function __construct(OrderRepository $orderRepository) {
$this->orderRepository = $orderRepository;
}
public function create(Request $request, Response $response): Response {
$data = $request->getParsedBody();
$user = $request->getAttribute('user');
try {
$order = $this->orderRepository->createOrder($user['sub'], $data);
return $response->withJson($order, 201);
} catch (InvalidArgumentException $e) {
return $response->withJson(['error' => $e->getMessage()], 400);
}
}
public function get(Request $request, Response $response, array $args): Response {
$order = $this->orderRepository->find($args['id']);
if (!$order) {
return $response->withJson(['error' => 'Order not found'], 404);
}
return $response->withJson($order);
}
}
五、性能优化策略
1. Redis缓存集成
// src/Services/CacheService.php
namespace AppServices;
use PredisClient;
class CacheService {
private $client;
private $ttl = 3600; // 1小时
public function __construct(string $dsn) {
$this->client = new Client($dsn);
}
public function get(string $key): ?string {
return $this->client->get($key);
}
public function set(string $key, string $value, ?int $ttl = null): void {
$this->client->setex($key, $ttl ?? $this->ttl, $value);
}
public function remember(string $key, callable $callback, ?int $ttl = null) {
if ($value = $this->get($key)) {
return unserialize($value);
}
$result = $callback();
$this->set($key, serialize($result), $ttl);
return $result;
}
}
2. OPcache配置优化
; php.ini 优化配置
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0 ; 生产环境禁用
opcache.enable_cli=1
六、自动化测试实现
1. 单元测试示例
// tests/Services/AuthServiceTest.php
namespace AppTestsServices;
use AppServicesAuthService;
use PHPUnitFrameworkTestCase;
class AuthServiceTest extends TestCase {
private $authService;
protected function setUp(): void {
$this->authService = new AuthService('secret-key');
}
public function testGenerateAndValidateToken(): void {
$user = ['id' => 1, 'name' => 'test', 'roles' => ['ROLE_USER']];
$token = $this->authService->generateToken($user);
$this->assertNotEmpty($token);
$payload = $this->authService->validateToken($token);
$this->assertEquals($user['id'], $payload['sub']);
}
public function testInvalidToken(): void {
$this->assertNull($this->authService->validateToken('invalid-token'));
}
}
2. API测试示例
// tests/Api/OrderApiTest.php
namespace AppTestsApi;
use AppTestsTestCase;
use GuzzleHttpClient;
class OrderApiTest extends TestCase {
private $client;
private $token;
protected function setUp(): void {
$this->client = new Client(['base_uri' => 'http://localhost']);
$this->token = $this->getAuthToken();
}
public function testCreateOrder(): void {
$response = $this->client->post('/api/orders', [
'headers' => ['Authorization' => 'Bearer ' . $this->token],
'json' => ['items' => [['productId' => 1, 'quantity' => 2]]]
]);
$this->assertEquals(201, $response->getStatusCode());
$data = json_decode($response->getBody(), true);
$this->assertArrayHasKey('orderNumber', $data);
}
private function getAuthToken(): string {
// 获取测试用户token
}
}
七、部署与监控
1. Docker部署配置
# docker-compose.yml
version: '3'
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:80"
volumes:
- .:/var/www/html
depends_on:
- redis
- db
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: order_api
redis:
image: redis:alpine
2. Prometheus监控集成
// src/Middlewares/MetricsMiddleware.php
namespace AppMiddlewares;
use PrometheusCollectorRegistry;
use PrometheusStorageRedis;
class MetricsMiddleware {
private $registry;
public function __construct() {
$redis = new Redis(['host' => 'redis']);
$this->registry = new CollectorRegistry($redis);
}
public function __invoke(Request $request, Handler $handler) {
$start = microtime(true);
$path = $request->getUri()->getPath();
try {
$response = $handler->handle($request);
$this->registry->getOrRegisterCounter(
'api', 'requests_total', 'Total requests', ['method', 'path', 'status']
)->inc([
$request->getMethod(),
$path,
$response->getStatusCode()
]);
return $response;
} finally {
$duration = microtime(true) - $start;
$this->registry->getOrRegisterHistogram(
'api', 'request_duration_seconds', 'Request duration', ['method', 'path'], [0.1, 0.5, 1, 2.5, 5]
)->observe($duration, [$request->getMethod(), $path]);
}
}
}
八、总结与扩展
本教程涵盖了:
- 现代化PHP API架构设计
- JWT认证与安全实践
- Doctrine ORM高级用法
- Redis性能优化方案
- 自动化测试与监控
扩展学习方向:
- GraphQL API实现
- 微服务间通信(gRPC)
- 服务网格(Service Mesh)集成
- Serverless部署方案