一、API设计原则与规范
在开始开发前,我们需要遵循RESTful API设计规范:
- 使用HTTP动词(GET, POST, PUT, DELETE)表示操作类型
- 资源使用名词复数形式(如 /api/v1/products)
- API版本控制(/api/v1/…)
- 统一响应格式(JSON)
- 合理的HTTP状态码(200, 201, 400, 401, 404, 500等)
二、项目初始化与配置
创建ThinkPHP项目并配置API专用环境:
composer create-project topthink/think tp-api cd tp-api
配置API路由(route/app.php):
use thinkfacadeRoute;
// API版本分组
Route::group('api', function() {
// V1版本API
Route::group('v1', function() {
// 产品资源路由
Route::resource('products', 'v1.Product');
// 用户认证路由
Route::post('login', 'v1.Auth/login');
Route::post('register', 'v1.Auth/register');
});
});
三、构建产品API模块
1. 创建产品模型
// app/model/Product.php
namespace appmodel;
use thinkModel;
class Product extends Model
{
// 设置表名
protected $name = 'products';
// 自动写入时间戳
protected $autoWriteTimestamp = true;
// 字段类型转换
protected $type = [
'price' => 'float',
'stock' => 'integer',
'is_on_sale' => 'boolean'
];
// 搜索器 - 按名称搜索
public function searchNameAttr($query, $value)
{
$query->where('name', 'like', '%' . $value . '%');
}
}
2. 创建API控制器
// app/controller/v1/Product.php
namespace appcontrollerv1;
use appmodelProduct;
use thinkfacadeRequest;
use thinkResponse;
class Product
{
/**
* 获取产品列表
* GET /api/v1/products
*/
public function index()
{
// 获取分页参数
$page = Request::param('page/d', 1);
$size = Request::param('size/d', 10);
// 获取搜索参数
$search = Request::param('search/s', '');
// 构建查询
$query = Product::withSearch(['name'], ['name' => $search]);
// 分页查询
$products = $query->paginate([
'page' => $page,
'list_rows' => $size
]);
// 返回JSON响应
return Response::create([
'code' => 200,
'message' => 'success',
'data' => [
'list' => $products->items(),
'total' => $products->total(),
'current_page' => $products->currentPage(),
'last_page' => $products->lastPage()
]
], 'json');
}
/**
* 创建新产品
* POST /api/v1/products
*/
public function save()
{
// 获取请求数据
$data = Request::only([
'name', 'description', 'price', 'stock', 'is_on_sale'
]);
// 数据验证
$validate = new thinkValidate([
'name|产品名称' => 'require|min:2',
'price|价格' => 'require|float|gt:0',
'stock|库存' => 'require|integer|egt:0',
]);
if (!$validate->check($data)) {
return Response::create([
'code' => 400,
'message' => $validate->getError()
], 'json', 400);
}
// 创建产品
$product = Product::create($data);
if ($product) {
return Response::create([
'code' => 201,
'message' => '产品创建成功',
'data' => $product
], 'json', 201);
}
return Response::create([
'code' => 500,
'message' => '产品创建失败'
], 'json', 500);
}
// 其他方法:read, update, delete...
}
四、实现JWT用户认证
1. 安装JWT扩展
composer require firebase/php-jwt
2. 创建认证服务
// app/service/JwtAuth.php
namespace appservice;
use FirebaseJWTJWT;
use FirebaseJWTKey;
class JwtAuth
{
// 密钥
private static $secret = 'your_secret_key';
// 创建Token
public static function createToken($userId)
{
$payload = [
'iss' => 'tp-api', // 签发者
'iat' => time(), // 签发时间
'exp' => time() + 7200, // 过期时间(2小时)
'sub' => $userId // 用户ID
];
return JWT::encode($payload, self::$secret, 'HS256');
}
// 验证Token
public static function verifyToken($token)
{
try {
$decoded = JWT::decode($token, new Key(self::$secret, 'HS256'));
return (array)$decoded;
} catch (Exception $e) {
return false;
}
}
}
3. 创建认证中间件
// app/middleware/JwtAuth.php
namespace appmiddleware;
use appserviceJwtAuth;
use thinkfacadeRequest;
class JwtAuth
{
public function handle($request, Closure $next)
{
// 获取Token
$token = Request::header('Authorization');
if (!$token) {
return json([
'code' => 401,
'message' => '缺少认证Token'
], 401);
}
// 验证Token
$authInfo = JwtAuth::verifyToken(str_replace('Bearer ', '', $token));
if (!$authInfo) {
return json([
'code' => 401,
'message' => '无效或过期的Token'
], 401);
}
// 将用户ID保存到请求对象
$request->userId = $authInfo['sub'];
return $next($request);
}
}
五、API速率限制与安全防护
1. 实现API速率限制
// app/middleware/RateLimit.php
namespace appmiddleware;
use thinkfacadeCache;
class RateLimit
{
public function handle($request, Closure $next)
{
$ip = $request->ip();
$key = 'api_rate_limit:' . $ip;
// 每分钟限制60次请求
$limit = 60;
$expire = 60; // 60秒
$count = Cache::get($key, 0);
if ($count >= $limit) {
return json([
'code' => 429,
'message' => '请求过于频繁,请稍后再试'
], 429);
}
// 增加计数
Cache::set($key, $count + 1, $expire);
return $next($request);
}
}
2. 配置全局中间件
// app/middleware.php
return [
// 全局中间件
appmiddlewareRateLimit::class,
// API分组中间件
'api' => [
appmiddlewareJwtAuth::class
]
];
六、API文档生成
使用ThinkPHP的注解功能生成API文档:
// 在控制器方法中添加注解
/**
* @title 获取产品列表
* @url GET /api/v1/products
* @param string name:page type:int desc:页码 default:1
* @param string name:size type:int desc:每页数量 default:10
* @param string name:search type:string desc:搜索关键词
* @return {"code":200,"message":"success","data":{"list":[],"total":0}}
*/
public function index()
{
// ...
}
使用扩展包自动生成文档:
composer require topthink/think-apidoc
七、API测试与调试
1. 使用Postman测试API
示例请求:
GET /api/v1/products?page=1&size=5&search=手机 Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
2. 测试响应示例
{
"code": 200,
"message": "success",
"data": {
"list": [
{
"id": 1,
"name": "智能手机",
"price": 3999.00,
"stock": 100,
"is_on_sale": true
},
// ...其他产品
],
"total": 15,
"current_page": 1,
"last_page": 3
}
}
八、性能优化策略
- 数据库优化:合理使用索引,避免N+1查询
- 缓存机制:使用Redis缓存频繁访问的数据
- 响应压缩:启用Gzip压缩减少传输大小
- 延迟加载:按需加载关联数据
- 队列处理:耗时操作异步处理
缓存优化示例
// 使用缓存优化产品详情查询
public function read($id)
{
$cacheKey = 'product:' . $id;
$product = cache($cacheKey);
if (!$product) {
$product = Product::find($id);
if ($product) {
cache($cacheKey, $product, 3600); // 缓存1小时
}
}
// ...
}
九、项目结构总结
最终项目结构如下:
tp-api/ ├─ app/ │ ├─ controller/ │ │ ├─ v1/ │ │ │ ├─ Product.php │ │ │ ├─ Auth.php │ ├─ model/ │ │ ├─ Product.php │ │ ├─ User.php │ ├─ middleware/ │ │ ├─ JwtAuth.php │ │ ├─ RateLimit.php │ ├─ service/ │ │ ├─ JwtAuth.php ├─ config/ │ ├─ cache.php │ ├─ middleware.php │ ├─ route.php ├─ database/ │ ├─ migrations/ │ │ ├─ create_products_table.php ├─ route/ │ ├─ app.php
十、API开发最佳实践
- 遵循RESTful设计规范
- 使用版本控制(v1, v2)
- 统一的错误处理机制
- 合理的HTTP状态码
- 数据验证与过滤
- 接口文档自动化
- 全面的单元测试
- API监控与日志

