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/coursesCourse/Course::search查询多个课程,或者分页查询
GET /api/courses/{courseId}Course/Course::get获取单个课程信息
POST /api/coursesCourse/Course::add创建课程
PATCH /api/courses/{courseId}Course/Course::update修改课程
DELETE /api/courses/{courseId}Course/Course::remove删除课程
GET /api/courses/{courseId}/membersCourse/CourseMember::search获取课程下的学员
GET /api/courses/{courseId}/members/{memberId}Course/CourseMember::get获取单个学员信息
POST /api/courses/{courseId}/membersCourse/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_levelsVipLevel/VipLevel::search查询所有的vip等级
GET /api/plugins/vip/vip_levels/{levelId}VipLevel/VipLevel::get获取单个vip等级信息

注解

ApiConf

在 API 调用前会使用的注解,目前提供了一个接口是否需要认证登陆的功能,默认所有接口都需要认证身份

使用方式:isRequiredAuth=false 即是表示该接口不需要认证

  1. class Course extends AbstractResource
  2. {
  3. /**
  4. * @ApiConf(isRequiredAuth=false)
  5. */
  6. public function get(ApiRequest $request, $courseId)
  7. {
  8. ......
  9. }
  10. }

ResponseFilter

该注解是用来选择接口返回值的过滤器

使用方式:

  1. lass MeCourseMember extends AbstractResource
  2. {
  3. /**
  4. * @ResponseFilter(class="ApiBundle\Api\Resource\Course\CourseMemberFilter", mode="public"))
  5. */
  6. public function get(ApiRequest $request, $courseId)
  7. {
  8. return $courseMember;
  9. }

$courseMember 会使用 ApiBundle\Api\Resource\Course\CourseMemberFilter 这个 filter 过滤属性

异常

请在 Resource 类里抛 Symfony\Component\HttpKernel\Exception\HttpException 的实例,这些异常类会返回正确的 HTTP 状态码

  1. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  2. ...
  3. throw new NotFoundHttpException('教学计划不存在', null, ErrorCode::RESOURCE_NOT_FOUND);
  4. ...

API 扩展

API 的扩展非常简单,目前提供两种方式扩展 API

插件 API 扩展

插件的 API 扩展不需要做任何配置,只需目录和 ApiBundle 一致即可

比如:

  1. <?php
  2. namespace VipPlugin\Api\Resource\VipLevel;
  3. use ApiBundle\Api\Resource\Resource;
  4. use Symfony\Component\HttpFoundation\Request;
  5. class VipLevel extends Resource
  6. {
  7. public function search(Request $request)
  8. {
  9. return $this->service('VipPlugin:Vip:LevelService')->findEnabledLevels();
  10. }
  11. }

CustomBundle API 扩展

CustomBundle API 扩展也很简单,只需要增加一行代码即可,在 CustomBundle 类的 boot 方法把 API 的命名空间注册到 api.resource.manager 就可以。 注册进来的 API 命名空间,支持 API 重写的机制,只要路由相同,会优先使用 CustomBundle 下的 API

  1. $this->container->get('api.resource.manager')->registerApi('CustomBundle\Api');

测试

现在 API 的集成测试使用的 Newman 来做,在 tests/api/Newman 目录下,如何增加自己的 API 测试,这里就不赘述了,自行研究。

最佳实践

URL规范

  • 资源都要加上s,表示是集合的概念
  • 如果资源是两个单词,使用_分割,比如vip等级,vip_levels