1、下载swagger-ui

GitHub地址:https://github.com/swagger-api/swagger-ui

2、修改 ThinkPHP 的 build.php ,执行命令生成需要创建的模块

  1. // 定义api模块的自动生成 (按照实际定义的文件名生成)
  2. 'api' => [
  3. '__file__' => ['common.php'],
  4. '__dir__' => ['controller'],
  5. 'controller' => ['Passport'],
  6. 'model' => [],
  7. 'view' => [],
  8. ],
    命令: php think build

3、修改刚刚生成的模块下的 config.php 文件

  1. return [
  2. 'default_return_type' => 'json', // 修改控制器默认输出json对象
  3. 'url_param_type' => 1, // URL参数方式 0 按名称成对解析 1 按顺序解析
  4. ];

4、在刚刚生成的 application/api/contorller/Passport.php 下添加这几个方法

  1. <?php
  2. namespace app\api\controller;
  3.  
  4. /**
  5. * swagger: 登录相关
  6. */
  7. class Passport
  8. {
  9. /**
  10. * post: 发送验证码
  11. * path: sendVerify/{phone}/{deviceType}
  12. * method: sendVerify
  13. * param: phone - {string} 手机号
  14. * param: deviceType - {int} = [0|1|2|3|4] 设备类型(0: android手机, 1: ios手机, 2: android平板, 3: ios平板, 4: pc)
  15. */
  16. public function sendVerify($phone, $deviceType) {
  17. return [
  18. 'code' => 200,
  19. 'message' => '发送验证码',
  20. 'data' => [
  21. 'phone' => $phone,
  22. 'deviceType' => $deviceType
  23. ]
  24. ];
  25. }
  26.  
  27. /**
  28. * post: 登陆
  29. * path: login
  30. * method: login
  31. * param: phone - {string} 手机号
  32. * param: password - {string} 密码
  33. * param: deviceType - {int} = [0|1|2|3|4] 设备类型(0: android手机, 1: ios手机, 2: android平板, 3: ios平板, 4: pc)
  34. * param: verifyCode - {string} = 0 验证码
  35. */
  36. public function login($phone, $password, $deviceType, $verifyCode = '0') {
  37. return [
  38. 'code' => 200,
  39. 'message' => '登陆成功',
  40. 'data' => [
  41. 'phone' => $phone,
  42. 'password' => $password,
  43. 'deviceType' => $deviceType,
  44. 'verifyCode' => $verifyCode
  45. ]
  46. ];
  47. }
  48.  
  49. /**
  50. * get: 获取配置
  51. * path: profile
  52. * method: profile
  53. * param: keys - {string[]} 需要获取配置的Key值数组
  54. */
  55. public function profile($keys) {
  56. return [
  57. 'code' => 200,
  58. 'message' => '获取成功',
  59. 'data' => $keys
  60. ];
  61. }
  62. }

5、把 swagger-ui 目录下的 dist 放到你的 public 目录下,然后更名为 swagger。

6、修改 swagger 下 index.html 的路径:

  1. window.onload = function() {
  2. // Begin Swagger UI call region
  3. const ui = SwaggerUIBundle({
  4. url : window.location.href.replace(window.location.hash, "").replace(/[^/]+$/, "swagger.json"),
  5. dom_id: '#swagger-ui',
  6. deepLinking: true,
  7. presets: [
  8. SwaggerUIBundle.presets.apis,
  9. SwaggerUIStandalonePreset
  10. ],
  11. plugins: [
  12. SwaggerUIBundle.plugins.DownloadUrl
  13. ],
  14. layout: "StandaloneLayout"
  15. })
  16. // End Swagger UI call region
  17.  
  18. window.ui = ui
  19. }

7、整合ThinkPHP 和 swaggerUI:

在 public 目录下新建 api.php

  1. <?php
  2.  
  3. // +----------------------------------------------------------------------
  4. // | ThinkPHP SWAGGER [ 够用就好 ]
  5. // +----------------------------------------------------------------------
  6. // | Copyright (c) 2016 http://jitlee.com All rights reserved.
  7. // +----------------------------------------------------------------------
  8. // | Licensed ( http://jitlee.com/licenses/LICENSE-1.0 )
  9. // +----------------------------------------------------------------------
  10. // | Author: Jitlee.Wan <www.wpj@163.com>
  11. // +----------------------------------------------------------------------
  12.  
  13. // 定义应用目录
  14. define('APP_PATH', __DIR__ . '/../application');
  15.  
  16. $tags = array(); // Tags对象
  17. $paths = array(); // Path数组
  18.  
  19. $module_dir = opendir(APP_PATH);
  20. while (($module_name = readdir($module_dir)) !== false) {
  21. if ($module_name != 'api') continue; //可以自己设置需要哪些模块用作api输出页面
  22. $module_path = APP_PATH . DIRECTORY_SEPARATOR . $module_name; //构建子目录路径
  23. if (is_dir($module_path)) {
  24. $module = strtolower($module_name);
  25.  
  26. $module_child_dir = opendir($module_path);
  27. while (($module_child_name = readdir($module_child_dir)) !== false) {
  28. $module_child_path = $module_path . DIRECTORY_SEPARATOR . $module_child_name; //构建子目录路径
  29. if (is_dir($module_child_path) && $module_child_name == 'controller') {
  30. $controller_dir = opendir($module_child_path);
  31. while (($controller_file = readdir($controller_dir)) !== false) {
  32. $controller_path = $module_child_path . DIRECTORY_SEPARATOR . $controller_file; //构建子目录路径
  33. $controller_name = strtolower(basename($controller_path, '.php'));
  34. $contents = file_get_contents($controller_path);
  35. if (preg_match_all('/swagger:\s*([^\n]+)/i', $contents, $swagger_matches)) {
  36.  
  37. // 添加tag
  38. $found_tag = false;
  39. foreach ($tags as $tag) {
  40. if ($tag['name'] == $controller_name) {
  41. $found_tag = true;
  42. break;
  43. }
  44. }
  45. if (!$found_tag) {
  46. array_push($tags, array(
  47. 'name' => $controller_name,
  48. 'description' => $swagger_matches[1][0]
  49. ));
  50. }
  51.  
  52. // 添加path
  53. if (preg_match_all('/\/\*((?!\*\/).)+\*\//s', $contents, $func_matches)) {
  54. $length = count($func_matches[0]);
  55. if ($length > 1) {
  56. for ($i = 1; $i < $length; $i++) {
  57. $func_array = array();
  58.  
  59. // 解析每个方法
  60. $func_contents = $func_matches[0][$i];
  61.  
  62. // 方法说明
  63. if (!preg_match_all('/(get|post|delete)\s*:\s*([^\n]+)/i', $func_contents, $matches)) {
  64. break;
  65. }
  66. $method = $matches[1][0];
  67. $summary = $matches[2][0];
  68.  
  69. // 路径
  70. if (!preg_match_all('/path\s*:\s*([^\n]+)/i', $func_contents, $matches)) {
  71. break;
  72. }
  73. $path = $matches[1][0];
  74.  
  75. // 方法名称
  76. $operations = explode('/', $path);
  77. $operationId = $operations[0];
  78. if (preg_match_all('/method\s*:\s*([^\n]+)/i', $func_contents, $matches)) {
  79. $operationId = $matches[1][0];
  80. }
  81.  
  82. $paths[$path] = array();
  83. $parameters = array();
  84. $func = array(
  85. 'tags' => [$controller_name],
  86. 'summary' => $summary,
  87. 'description' => '',
  88. 'operationId' => $operationId,
  89. 'produces' => ['application/json']
  90. );
  91.  
  92. // 参数
  93. $pattern = '/param\s*:\s*(?<name>\w+)\s*-\s*\{(?<type>\w+(?<array>\[\])?)\}\s*(=\s*((\[(?<enum>[^]]+)\])|(?<default>[^\s]+))\s*)?(?<summary>[^*]+)/i';
  94. if (preg_match_all($pattern, $func_contents, $matches)) {
  95. $names = $matches['name']; // 参数名称
  96. $types = $matches['type']; // 参数类型
  97. $enums = $matches['enum']; // 参数枚举
  98. $defaults = $matches['default']; // 默认值
  99. $summarys = $matches['summary']; // 参数说明
  100. $arrays = $matches['array']; // 参数说明
  101.  
  102. $params_count = count($names);
  103. for ($j = 0; $j < $params_count; $j++) {
  104. $in = $method == 'get' ? 'query' : 'formData';
  105. if (strpos($path, '{' . $names[$j] . '}') !== false) {
  106. $in = 'path';
  107. }
  108.  
  109. $parameter = array(
  110. 'name' => $names[$j],
  111. 'in' => $in,
  112. 'required' => true,
  113. 'description' => $summarys[$j]
  114. );
  115.  
  116. if ($defaults[$j] !== '') {
  117. $parameter['required'] = false;
  118. $parameter['defaultValue'] = $defaults[$j];
  119. }
  120.  
  121. $type = str_replace('[]', '', $types[$j]);
  122. if ($type == 'int') {
  123. $type = 'integer';
  124. }
  125.  
  126. if ($arrays[$j] != '') { // 是否数据参数
  127. $parameter['type'] = 'array';
  128. $parameter['items'] = array(
  129. 'type' => str_replace('[]', '', $type)
  130. );
  131. $parameter['collectionFormat'] = 'brackets'; // url带中括号
  132. // $parameter['collectionFormat'] = 'multi'; // url不带中括号
  133. } else if ($enums[$j] != '') { // 是否枚举参数
  134. $enum = explode('|', $enums[$j]);
  135. $parameter['type'] = $type;
  136. $parameter['enum'] = $enum;
  137. } else {
  138. $parameter['type'] = $type;
  139. }
  140. array_push($parameters, $parameter);
  141. }
  142. }
  143. $func['parameters'] = $parameters;
  144. // 生成api访问路径
  145. $paths['/' . $module . '/' . $controller_name . '/' . $path][$method] = $func;
  146. }
  147. }
  148. }
  149. }
  150. }
  151. closedir($controller_dir);
  152. }
  153. }
  154. closedir($module_child_dir);
  155. }
  156. }
  157. closedir($module_dir);
  158.  
  159. $swagger = array(
  160. 'swagger' => '2.0',
  161. 'info' => array(
  162. 'description' => 'APP 后台服务',
  163. 'version' => '1.0.0',
  164. 'title' => '[我的APP]Swagger',
  165. 'termsOfService' => 'http://www.ritacc.cn/',
  166. 'contact' => array(
  167. 'email' => 'www.wpj@163.com'
  168. ),
  169. 'license' => array(
  170. 'name' => 'Apache 2.0',
  171. 'url' => 'http://www.apache.org/licenses/LICENSE-2.0.html'
  172. )
  173. ),
  174. 'host' => $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'],
  175. 'basePath' => '',
  176. 'tags' => $tags,
  177. 'schemes' => [
  178. 'http'
  179. ],
  180. 'paths' => $paths,
  181. 'securityDefinitions' => array(),
  182. 'definitions' => array(),
  183. 'externalDocs' => array(
  184. 'description' => 'Find out more about Swagger',
  185. 'url' => 'http://swagger.io'
  186. )
  187. );
  188.  
  189. $jsonFile = fopen("swagger/swagger.json", "w") or die("Unable to open file!");
  190. fwrite($jsonFile, json_encode($swagger));
  191. fclose($jsonFile);
  192.  
  193. // 跳转到Swagger UI
  194. $url = '/swagger/index.html';
  195. Header('HTTP/1.1 303 See Other');
  196. Header("Location: $url");
  197. exit;

8、打开浏览器运行 public 下的 api.php 就 ok 了。

ThinkPHP 使用 SwaggerUi 自动生成 api 文档的更多相关文章

  1. SpringBoot结合Swagger2自动生成api文档

    首先在pom.xml中添加如下依赖,其它web,lombok等依赖自行添加 <dependency> <groupId>io.springfox</groupId> ...

  2. Spring Boot 项目学习 (四) Spring Boot整合Swagger2自动生成API文档

    0 引言 在做服务端开发的时候,难免会涉及到API 接口文档的编写,可以经历过手写API 文档的过程,就会发现,一个自动生成API文档可以提高多少的效率. 以下列举几个手写API 文档的痛点: 文档需 ...

  3. springboot 集成 swagger 自动生成API文档

    Swagger是一个规范和完整的框架,用于生成.描述.调用和可视化RESTful风格的Web服务.简单来说,Swagger是一个功能强大的接口管理工具,并且提供了多种编程语言的前后端分离解决方案. S ...

  4. 使用bee自动生成api文档

    beego中的bee工具可以方便的自动生成api文档,基于数据库字段,自动生成golang版基于beego的crud代码,方法如下: 1.进入到gopath目录的src下执行命令: bee api a ...

  5. 自动生成api文档

    vs2010代码注释自动生成api文档 最近做了一些接口,提供其他人调用,要写个api文档,可是我想代码注释已经写了说明,能不能直接把代码注释生成api?于是找到以下方法 环境:vs2010 先下载安 ...

  6. 试试使用 eolinker 扫描 GitLab 代码注释自动生成 API 文档?

    前言: 一般写完代码之后,还要将各类参数注解写入API文档,方便后续进行对接和测试,这个过程通常都很麻烦,如果有工具可以读取代码注释直接生成API文档的话,那会十分方便. 此前一直都是在使用eolin ...

  7. go实践之swagger自动生成api文档

    文章目录 go实践之swagger自动生成api文档 1.安装需要用到的包 2.接口代码支持swagger 3. 生成swagger接口 go实践之swagger自动生成api文档 作为一个后端开发, ...

  8. Django restful framework中自动生成API文档

    自动生成api文档(不管是函数视图还是类视图都能显示) 1.安装rest_framework_swagger库 pip install django-rest-swagger 2.在项目下的 urls ...

  9. 【转】Django restful framework中自动生成API文档

    转自 https://www.cnblogs.com/sui776265233/p/11350434.html 自动生成api文档(不管是函数视图还是类视图都能显示) 1.安装rest_framewo ...

随机推荐

  1. CodeForces 837F - Prefix Sums | Educational Codeforces Round 26

    按tutorial打的我血崩,死活挂第四组- - 思路来自FXXL /* CodeForces 837F - Prefix Sums [ 二分,组合数 ] | Educational Codeforc ...

  2. .net core Areas区域

    //使用MVC app.UseMvc(routes => { routes.MapRoute( name: "areas", template: "{area:ex ...

  3. Python 3 格式化字符串的几种方法!

    Python 3 格式化字符串的几种方法! %s和%d,%s是用来给字符串占位置,%d是给数字占位置,简单解释下: a = 'this is %s %s' % ('an','apple') 程序输出的 ...

  4. 03 JavaScript的使用

    01 注册界面的校验 <!-- 作者:offline 时间:2018-09-05 描述:通常在CSS中使用类选择器,在JS中使用id选择器,两者区分开. 在页面跳转时要先把要跳转的页面用浏览器打 ...

  5. Visual Stdio的使用

    以下基于vs2017版本 part 1: 问题及解决 1.命令窗口一闪而过 右键项目,选择属性--连接器---系统---子系统---选择控制台. 2.修改默认启动项目 右键解决方案,选择属性,选择当前 ...

  6. CSP-S 模拟测试 45 题解

    由于咕掉的题解太多了,所以只能趁改完不动题的时间,来补补坑qwq,还是太弱了. 考试过程: 到新机房的第一次考试,貌似海星? 第一题一开始就觉得是个贪心,但以为所有小怪兽都要打完,所以想复杂了,但后来 ...

  7. 从斐波那契数列看java方法的调用过程

    先看斐波那契数列的定义: 斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为 ...

  8. 数据结构实验之链表二:逆序建立链表(SDUT 2117)

    题目链接 #include <bits/stdc++.h> using namespace std; struct node { int data; struct node *next; ...

  9. Jmeter(十三)阶梯式压测

    阶梯式压测,就是对系统的压力呈现阶梯性增加的过程,每个阶段压力值都要增加一个数量值,最终达到一个预期值.然后保持该压力值,持续运行一段时间. Jmeter中有个插件可以实现这个场景,这个插件就是:Co ...

  10. Difference Between static and default methods in interface

    I was learning through interfaces when I noticed that you can now define static and default methods ...