前后端分离的工作模式于今是非常流行了,前后端工作的对接,就离开不了api文档的辅助。

 

根据自己以往的工作经历,以及了解的一些资讯,api文档的建立,无非以下几种方式:

1. word文档模板

2. 第三方平台,类如postman、showdoc等

3. 框架内单独自定义一套绑定路由的结构,再解析成html页面

4. 在框架内每个路由的方法的注释块里按照规则写注释,再解析生成api文档

5. 框架内直接编辑markdown文件,再转换成html页面

 

根据自己的使用心得,发表一下个人看法。

1.word文档模板:

这是在第一家公司–富士康科技集团–接触到的,就是公司准备好了一个api文档的模板,每个api对应一个表格,在表格里填上对应的路径(path),调用方式(method)、请求参数,返回数据结构等信息。对于刚开始新增api是ok的,当时测试工作和后端正好在不同城市,api文档可以起到很好的沟通作用。但对于后期维护,总要完善了一个接口,就要对应的去word文档里查找并修改,一旦后端没有或忘记更新了,随着时间过着越久,反而后面越容易把自己带到坑里去。

 

优点:前期工作少,拿个模板就可以开写了。

缺点:更新接口不是很方便。

 

2.第三方平台:

工作经历中有一家用到,无非就是把api信息录入到第三方平台,本人很是反感。尤其是需要像form表单一样一个个栏位填写,一个个接口的添加,简直是作践后端的时间价值。维护?简直是更乱,因为第三方平台需要登录账号,每多一小步,人发懒的概率就越大,时间久了,api文档不同步的概率和范围就更大更广。

 

工作中现在我一直用postman测试接口,所以postman是必用的工具。至于用它写api文档是否支持又是否方便,本人没有接触过,就不发表看法了。

showdoc是编辑markdown方式,对于添加api接口,撰写体验还是很不错的。但接口信息像postman一样一条条分开的,查找浏览不方便,维护一般首先就是要查找,所以维护体验也感觉很不好。所以以往有的公司,项目涉及到成员多批变迁时,就有那种同一个功能出现几个不同的api。因为新增接口信息可以避免去了解去确认此功能接口之前是否已经撰写过,人都有惰性,就干脆直接新增了接口文档记录,结果就自然导致同样接口的文档记录有两三条,文档就慢慢失去了原本的价值:辅助新员工快速了解功能和开展工作。

 

那什么时候考虑第三方平台呢?

有的第三方平台实现了接口功能实时监控及安全防护,就是有受到攻击或者接口挂掉的情况时,可以给你手机发短信通知你。如果你非常需要这个,那你就用吧。

 

优点:前期工作少,有可能带有接口安全防护和实时监控,避免因为接口挂掉带来利益损失。

缺点:不仅多了一步登录操作,而且大多产品设计的页面体验不好,不利于快速新增及更新文档,管理不好的话,容易失去文档的本身价值。

 

3.自定义绑定路由的结构:

这是我自己起的名字,可能不太准确。

大体实现方式就是,接口写好了并定好了路由,就在另外一个php文件针对每一条路由用php语言来定义好一个api文档所需要的信息。

例如如下:

$app->route("user/getlist")
->request(
        array(
            'page' => '1 //第几页',
            'page_size' => '10 //每页数据条数'
        )
    )
    ->method('post')
    ->response(
        array(
            'data' => array(
                'total_count' => '199 //总记录条数',
                'list' => array(
                    'username' => 'coderzhai //姓名',
                    'gender' => '1 //1-男 2-女'
                )
            )
        )
    )

然后自己再根据上述结构解析出对应数据展示在页面里。

 

优点:跟后端代码一起,文档更新及维护更方便。文档按功能划分、按区域划分、按版本划分、增加用户权限控制等实现比较方便。

缺点:由于以上代码是用php语言编写的,一旦遇上哪里少了括号或是逗号等php语法错误,就会造成文档页面无法浏览。还需要费时间的去找到问题的所在并及时修复它。接口路由不适宜用resource组合的,因为具体对应增删查改哪几个接口不好确定。

 

4.利用方法的注释块生成api文档

这种方式是了解apidoc时了解到的,就是按照规定的规则在接口方法的注释块里备注信息,类如如下:

/**
* @api {get} /user/:id request user information
* @apiname getuser
* @apigroup user
*
* @apiparam {number} id users unique id.
*
* @apisuccess {string} firstname firstname of the user.
* @apisuccess {string} lastname lastname of the user.
*
* @apisuccessexample success-response:
* http/1.1 200 ok
* {
* "firstname": "john",
* "lastname": "doe"
* }
*
* @apierror usernotfound the id of the user was not found.
*
* @apierrorexample error-response:
* http/1.1 404 not found
* {
* "error": "usernotfound"
* }
*/

以上是我从网上随便粘贴的一段,虽说本人写代码不是非常洁癖,但这么一大串的注释,本人看着就表示不爽,所以没一点深入了解它的欲望。不介意的就自行研究喽。

 

优点:同后端代码一起,更新维护距离近在咫尺。

缺点:注释太大块了,感觉影响看功能,代码显得十分拖沓,影响美观。

 

 

5.框架内直接编辑markdown文件

这就是我目前最喜欢的方式,也是本文要讲解实现的方式。

 

优点:同后端代码一起,维护方便;markdown格式编写,文档撰写省时;所有接口在一个页面或几个划分好的页面里,方便浏览和查找。

缺点:要做一些前期工作来实现。但现在有了现成的插件和本文的教程支持,缺点就可以忽略不计了。

 

 

以上几种方式都比较完了,现在我就来实现在laravel内撰写api文档,支持网页浏览。

 

要实现的功能主要就是把指定的md文件转换成html。

github上有一个人气很旺的插件:erusev/parsedown, 地址:

 

一般项目涉及pc后台,我这里就新增一个路由文件专门来放这些后台的api。

 

1.安装erusev/parsedown插件。

编辑composer.json文件,添加代码如下:

 "require": {
"php": "^7.1.3",
"fideloper/proxy": "^4.0",
"laravel/framework": "5.7.*",
"laravel/tinker": "^1.0",
"erusev/parsedown":"^1.6" //新增的
},

 

项目根目录下执行composer install进行安装。在vendor文件夹下可看到erusev文件夹,则代表安装成功。

 

2.在app/providers/routeserviceprovider.php中引入自定义的后台路由文件。

public function map()
{
$this->mapapiroutes();
$this->mapwebroutes();
//新增的后台路由
$this->mapadminroutes();
}

protected function mapadminroutes()
{
route::prefix('admin')
// ->middleware('api') //避免篇幅过长,中间件的引入这里就忽略了
->namespace($this->namespace)
->group(base_path('routes/admin.php'));
}

 

 

3.添加路由,添加控制器,先调试,要可以成功进入控制器方法。

routes问价下新增admin.php文件,里面加上我们的api文档路由:

route::get('/apidoc', 'admin\apidoccontroller@showdoc');  //注意后面是反斜杠\,否则会报错

laravel框架入口是public/index.php,为了隐藏这个就自定义个本地解析的名称,编辑apache的httpd-vhosts文件如下:

<virtualhost *:80>
servername testlaravel
documentroot e:/wamp64/www/laravel/public
<directory "e:/wamp64/www/laravel/public/">
options +indexes +includes +followsymlinks +multiviews
allowoverride all
allow from all
header set access-control-allow-origin *
</directory>
rewriteengine on
rewritecond $1 !^(index\.php|images|robots\.txt)
rewriterule ^(.*)$ /index.php/$1 [l]
</virtualhost>

编辑好后,重启apache服务。

 

现在来加控制器,laravel可以用artisan命令生成,方便快捷。在项目根目录执行如下命令:

php artisan make:controller admin/apidoccontroller

接下来编辑controller文件:

<?php

namespace app\http\controllers\admin;

use illuminate\http\request;
use app\http\controllers\controller;

class apidoccontroller extends controller
{
public function showdoc(request $request){
echo "hello coder";
}
}

浏览器输入http://laraveltest/admin/apidoc,直到出现hello coder后才可以进行后面步骤。

 

4. 使用插件实现markdown转为html

功能很简单,就直接上代码啦。

<?php

namespace app\http\controllers\admin;

use illuminate\http\request;
use app\http\controllers\controller;
use parsedown;

class apidoccontroller extends controller
{
public function __construct(){
$this->markdownparser = new parsedown();
}

public function showdoc(request $request){
$filecontent = file_get_contents(storage_path('doc/admin_api.md'));
$htmlcontent = $this->convertmarkdowntohtml($filecontent);
$content = $this->convertmarkdowntohtml($htmlcontent);
return view('apidoc_admin')->with('content',$content);
}

public function convertmarkdowntohtml($markdown)
{
$convertedhmtl = $this->markdownparser->setbreaksenabled(true)->text($markdown);
return $convertedhmtl;
}
}

本文推荐的就是用markdown编辑api的方式,md就是markdown文件的后缀,我现在把这个文件放在storage/doc/admin_api.md处。

为了测试,我暂时在文件里粘贴了一个markdown格式的api:

**简要描述:** 

- 用户登录接口

**请求url:**
- ` http://xx.com/api/user/login `

**请求方式:**
- post

**参数:**

|参数名|必选|类型|说明|
|:---- |:---|:----- |----- |
|username |是 |string |用户名 |
|password |是 |string | 密码 |


**返回示例**
```
{
"error_code": 0,
"data": {
"uid": "1",
"username": "zhai coder",
"name": "翟码农",
"groupid": 2 ,
"reg_time": "2019-08-01",
"last_login_time": "0",
}
}
```
**返回参数说明**

|参数名|类型|说明|
|:----- |:-----|----- |
|groupid |int |用户组id,1:超级管理员;2:普通用户 |

**备注**

- 更多返回错误代码请看首页的错误代码描述

最后还需要准备好一个view文件。

我是创建在resources/views文件夹下的,文件名为:apidoc_admin.blade.php。

方便表达我强烈的推荐意愿,css样式我都给大家调好了,大家直接拿去用吧。

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getlocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>laravel</title>
<style>
html, body {
background-color: #fff;
color: #636b6f;
font-family: 'nunito', sans-serif;
font-weight: 200;
height: 100vh;
margin: 0;
color:#222; }
.container{
width:800px;
margin:10px auto;
padding:20px;
border-left:2px solid silver;
border-right:2px solid silver; }
table th,td{
border:1px solid #ede;
padding:5px 10px; }
pre{
background: #666;
color: white;
padding: 20px 10px;
font-family: yahei;
overflow: auto; }
li code{
font-size: 28px;
color: #4eb4ee;
font-weight: bold;
}
</style>
</head>
<body>
<div class="container">
{!! $content !!}
</div>
</body>
</html>

 

到这里,所有工作算是完成了。

在浏览器输入api文档访问地址:

http://testlaravel/admin/apidoc

一幅如画卷般的文档页面就出来喽。