API 开发文档
TODO
- 多版本控制
- OAuth 2.0认证 RFC6749
- 没有认证的话,接口不能翻页
- app 请求日志调优
- n+1查询问题排查
- token过期的解决方案
- 新的Resource寻址解决方案
- 将API重构成框架,参考silex
- 重构oauth2 bundle,去掉ORM
- api session 解决方案,session统一
介绍
ES
API
遵循 REST
的最佳实践开发的,这里只介绍如何在 ES
开发接口,怎么使用不做介绍,如果还不知道如何使用, 可以参考文档。
路由
API 实现了自动路由的功能,不需要自己写路由,只要在相应的目录下面创建相应的 PHP
文件即可。
ApiBundle下的接口路由定义
Resource类目录为ApiBundle/Api/Resource
规则如下:
URL | 类和方法 | 描述 |
---|---|---|
GET /api/courses | Course/Course::search | 查询多个课程,或者分页查询 |
GET /api/courses/{courseId} | Course/Course::get | 获取单个课程信息 |
POST /api/courses | Course/Course::add | 创建课程 |
PATCH /api/courses/{courseId} | Course/Course::update | 修改课程 |
DELETE /api/courses/{courseId} | Course/Course::remove | 删除课程 |
GET /api/courses/{courseId}/members | Course/CourseMember::search | 获取课程下的学员 |
GET /api/courses/{courseId}/members/{memberId} | Course/CourseMember::get | 获取单个学员信息 |
POST /api/courses/{courseId}/members | Course/CourseMember::add | 添加课程学员 |
PATCH /api/courses/{courseId}/members/{memberId} | Course/CourseMember::update | 修改学员信息 |
DELETE /api/courses/{courseId}/members/{memberId} | Course/CourseMember::remove | 删除课程学员 |
插件下的接口路由定义
Resource类目录为{PluginName}/Api/Resource
eg: VipPlugin/Api/Resource
URL 和ApiBundle的差不多,不过前面需要加上/plugins/{pluginName}
URL | 类和方法 | 描述 |
---|---|---|
GET /api/plugins/vip/vip_levels | VipLevel/VipLevel::search | 查询所有的vip等级 |
GET /api/plugins/vip/vip_levels/{levelId} | VipLevel/VipLevel::get | 获取单个vip等级信息 |
注解
ApiConf
在 API 调用前会使用的注解,目前提供了一个接口是否需要认证登陆的功能,默认所有接口都需要认证身份
使用方式:isRequiredAuth=false
即是表示该接口不需要认证
class Course extends AbstractResource
{
/**
* @ApiConf(isRequiredAuth=false)
*/
public function get(ApiRequest $request, $courseId)
{
......
}
}
ResponseFilter
该注解是用来选择接口返回值的过滤器
使用方式:
lass MeCourseMember extends AbstractResource
{
/**
* @ResponseFilter(class="ApiBundle\Api\Resource\Course\CourseMemberFilter", mode="public"))
*/
public function get(ApiRequest $request, $courseId)
{
return $courseMember;
}
$courseMember
会使用 ApiBundle\Api\Resource\Course\CourseMemberFilter
这个 filter
过滤属性
异常
请在 Resource
类里抛 Symfony\Component\HttpKernel\Exception\HttpException
的实例,这些异常类会返回正确的 HTTP
状态码
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
...
throw new NotFoundHttpException('教学计划不存在', null, ErrorCode::RESOURCE_NOT_FOUND);
...
API 扩展
API 的扩展非常简单,目前提供两种方式扩展 API
插件 API 扩展
插件的 API 扩展不需要做任何配置,只需目录和 ApiBundle 一致即可
比如:
<?php
namespace VipPlugin\Api\Resource\VipLevel;
use ApiBundle\Api\Resource\Resource;
use Symfony\Component\HttpFoundation\Request;
class VipLevel extends Resource
{
public function search(Request $request)
{
return $this->service('VipPlugin:Vip:LevelService')->findEnabledLevels();
}
}
CustomBundle API 扩展
CustomBundle API 扩展也很简单,只需要增加一行代码即可,在 CustomBundle 类的 boot 方法把 API 的命名空间注册到 api.resource.manager
就可以。 注册进来的 API 命名空间,支持 API 重写的机制,只要路由相同,会优先使用 CustomBundle 下的 API
$this->container->get('api.resource.manager')->registerApi('CustomBundle\Api');
测试
现在 API 的集成测试使用的 Newman
来做,在 tests/api/Newman
目录下,如何增加自己的 API 测试,这里就不赘述了,自行研究。
最佳实践
URL规范
- 资源都要加上s,表示是集合的概念
- 如果资源是两个单词,使用_分割,比如vip等级,vip_levels