thinkphp结合swagger详细介绍,下载安装自动生成接口文档,附案例使用


第一步:安装swagger-ui前端

 用cd命令进入到存放静态文件的目录,例如public目录。执行下面命令:

git clone https://github.com/swagger-api/swagger-ui.git

 注意:上面的命令,下载的是当前最新版本3.0,但是3.0有个已知的问题,不支持中文。如果想支持中文,需要指定版本。

git clone --branch v2.2.10 https://github.com/swagger-api/swagger-ui.git

第二步:安装swagger-php后端

 进入tp框架找到根目录下,打开composer.json找到require项,添加一行,然后使用更新命令。

"zircote/swagger-php": "*"

 注意,每行用逗号分隔,不要忘了。

 或者执行命令:

composer require "zircote/swagger-php"

 注意:这个命令默认下载的是当前最新的版本,也就是3.x。我到git上查了一下,想要跟swagger-ui的2.x版本配合使用,需要使用swagger-php 2.x版本。指定版本:

composer require "zircote/swagger-php:2.0.13"

第三步:生成swagger.json文件

1、教程上,让执行下面命令(实际执行的命令,要根据你那边的目录来确定)

php E:/WampServer/WWW/tpSwagger/tp5/vendor/zircote/swagger-php/bin/swagger E:/WampServer/WWW/tpSwagger/tp5/vendor/zircote/swagger-php/Examples -o E:/WampServer/WWW/tpSwagger/tp5/swaggerApi/swagger.json

第1个路径是你安装成功后组件的路径;

第2个路径是你想要生成这个目录下所有用swagger方式注释的php文件,把所有注释生成api文档;

第3个路径是你存放生成swagger.json的路径。

可能是我这边默认安装的是新版的swagger(查看版本是3.0),提示找不到swagger

我到bin这个目录,发现没有swagger文件,但是有一个openapi文件。

于是就把bin/swagger改为bin/openapi,再次执行。

结果虽然报了很多警告,但是确实生成了json文件。

2、swagger-ui加载生成的json文件

进入到swagger-ui的下载目录,找到dist目录,打开里面的index.html文件,修改文件引用的.json文件的路径为你的json文件的路径(就是上面生成的那个swagger.json)

如果json文件的目录设置不对,则会提示Failed to load API definition.

3、编写控制器方法生成swagger.json:

如果我们每次修改了api,还要手动执行第三步的代码,有些繁琐,那我们就在控制器中写一个方法,每次访问swagger-ui的时候自动执行,然后跳转到前台swagger界面中。

快速更新文档

复制代码
<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{    public function index(){        
        $path = 'D:/WampServer/WWW/tpSwagger/tp5/application'; //你想要哪个文件夹下面的注释生成对应的API文档
        $swagger = \OpenApi\scan($path);        
        // header('Content-Type: application/json');
        // echo $swagger;
        $swagger_json_path = 'D:/WampServer/WWW/tpSwagger/tp5/swaggerApi/swagger.json';        
        $res = file_put_contents($swagger_json_path, $swagger);        
        if ($res == true) {           
             $this->redirect('http://localhost/tpSwagger/swagger-ui/dist/index.html');
        }
    }

}
复制代码

我这边在使用Swagger方法的时候,不能用这个\OpenApi\scan($path);提示找不到方法,需要用\Swagger\scan($path);

扫描的结果是对象,如果要写入文件,需要转换为字符串。另外在写入文件的时候,遇到权限问题。我最后没有使用file_put_contents函数

复制代码
        $path = APP_PATH.'portal/test'; //你想要哪个文件夹下面的注释生成对应的API文档
        $swagger = \Swagger\scan($path);        
        // header('Content-Type: application/json');
        // echo $swagger;
        $swagger_json_path = ROOT_PATH.'public/swaggerApi/swagger.json';        // 检测模板目录
        $dir = dirname($swagger_json_path);        
        if (!is_dir($dir)) {            
             mkdir($dir, 0755, true);
        }

        $myfile = fopen($swagger_json_path, "w") or die("Unable to open file!");        
        $swagger=json_encode($swagger, true);        
        fwrite($myfile, $swagger);        
        fclose($myfile);
复制代码

 

第四步:编写swagger注释

控制器的注释写法

/**
 * @SWG\Resource(
 *  basePath="http://skyapi.dev",
 *  resourcePath="/vps",
 *  @SWG\Api(
 *   path="/vps",
 *   @SWG\Operation(
 *    method="GET",
 *    type="array",
 *    summary="Fetch vps lists",
 *    nickname="vps/index",
 *    @SWG\Parameter(
 *     name="expand",
 *     description="Models to expand",
 *     paramType="query",
 *     type="string",
 *     defaultValue="vps,os_template"
 *    )
 *   )
 *  )
 * )
 */
class VpsController extends Controller
{
    // ...
}

这只是个简单的实例具体的注释写法请自己百度

2、swagger注释使用

参考这个(写的比较全面):https://learnku.com/laravel/t/7430/how-to-write-api-documents-based-on-swagger-php#747b67

还有这个:https://blog.csdn。net/dyt19941205/article/details/79025266(链接中‘。’换成‘.’访问哈,不然发表不了)

这个:https://www.jianshu.com/p/554cd3762ab1

结合上面这几篇文章学习写了一个借口文档,也就四个方法,基本需要的东西都有了,以后再写文档可以照搬了

写接口文档真的很费时间,尤其写在php注释里,比较简单的文档可以使用swagger提供的编辑工具,直接在上面修改json文件后导出使用就可以了:http://editor.swagger.io/

下面给一个完整的接口注释:

复制代码
<?php
namespace app\app\controller;use think\Controller;use think\Request;use think\Db;/**

 * @SWG\Swagger(

 *   schemes={"http"},

 *   host="127.0.0.1",
 *   basePath="/restudy/public/index.php/app/",

 *   consumes={"multipart/form-data","X-Requested-With/XMLHttpRequest"},     
 *   produces={"application/json"},

 *   @SWG\Info(

 *     version="1.0",

 *     title="我的测试学习api项目",

 *     description="接口学习,目前只写了一个Api类,把顶级栏目接口、二级栏目接口、文章列表接口、文章内容接口写到了一起"

 *   ),

 *

 *   @SWG\Tag(

 *     name="Api",
 *     description="新闻webapp四大接口",
        
 *   ),

 * ) */class Api extends Controller
{  /**

     *@SWG\Get(path="/api/gettopnav", tags={"Api"},

     *   summary="获取顶级栏目列表",

     *   description="获取顶级栏目列表,返回栏目id,名称,和是否启用栏目", 
      @SWG\Parameter(
     *         description="ajax请求要加上X-Requested-With:XMLHttpRequest头字段",
     *         format="string",
     *         in="header",
     *         name="X-Requested-With",
     *         required=true,
     *         type="string",
               default="XMLHttpRequest",
     *         
     *     ),       
         @SWG\Response(response="200", description="操作成功", @SWG\Schema(
 *         required={""},
 *         @SWG\Property(
 *              property="code",
 *              type="integer",
                example=200,
 *         ),
 *         @SWG\Property(
 *              property="msg",
 *              type="string",
                example="顶级栏目返回成功",
 *         ),
            @SWG\Property(
 *              property="data",
 *              type="object",
                example="[{cate_id:5,cate_name:'栏目1',cate_ison:1},{cate_id:6,cate_name:'栏目2',cate_ison:0}]",
 *         ),
 *         
 *     )),
         @SWG\Response(response="201", description="数据为空", @SWG\Schema(
 *         required={""},
 *         @SWG\Property(
 *              property="code",
 *              type="integer",
                example=201,
 *         ),
 *         @SWG\Property(
 *              property="msg",
 *              type="string",
                example="数据为空!",
 *         ),
 *         
 *     )),
         @SWG\Response(response="400", description="非法请求,不是ajax请求", @SWG\Schema(
 *         required={""},
 *         @SWG\Property(
 *              property="code",
 *              type="integer",
                example=400,
 *         ),
 *         @SWG\Property(
 *              property="msg",
 *              type="string",
                example="非法请求",
 *         ),
 *         
 *     )),

     * )     */

    //顶级栏目接口
    public function getTopnav(){        if(request()->isAjax()){            $data=Db::table('re_cate')->where('cate_pid',0)->field('cate_id,cate_name,cate_ison')->select();            if(!empty($data)){                return json(['code'=>200,'msg'=>'顶级栏目返回成功','data'=>$data]);
            }else{                return json(['code'=>201,'msg'=>'数据为空!']);
            }
            
        }else{            return json(['code'=>400,'msg'=>'非法请求']);
        }
        

    }    /**

     *@SWG\Post(path="/api/getsonnav", tags={"Api"},

     *   summary="获取二级栏目列表",

     *   description="根据栏目id获取二级栏目列表,返回栏目id,名称,和是否启用栏目", 
      @SWG\Parameter(
     *         description="ajax请求要加上X-Requested-With:XMLHttpRequest头字段",
     *         format="string",
     *         in="header",
     *         name="X-Requested-With",
     *         required=true,
     *         type="string",
               default="XMLHttpRequest",
     *         
     *     ),  
     *   @SWG\Parameter(name="id",type="integer", required=true, in="formData",

     *     description="顶级栏目id"

     *   ),     
         @SWG\Response(response="200", description="操作成功", @SWG\Schema(
 *         required={""},
 *         @SWG\Property(
 *              property="code",
 *              type="integer",
                example=200,
 *         ),
 *         @SWG\Property(
 *              property="msg",
 *              type="string",
                example="二级栏目返回成功",
 *         ),
            @SWG\Property(
 *              property="data",
 *              type="object",
                example="[{cate_id:5,cate_name:'栏目1',cate_ison:1},{cate_id:6,cate_name:'栏目2',cate_ison:0}]",
 *         ),
 *         
 *     )),
         @SWG\Response(response="201", description="数据为空", @SWG\Schema(
 *         required={""},
 *         @SWG\Property(
 *              property="code",
 *              type="integer",
                example=201,
 *         ),
 *         @SWG\Property(
 *              property="msg",
 *              type="string",
                example="数据为空!",
 *         ),
 *         
 *     )),
         @SWG\Response(response="400", description="非法请求,不是ajax请求", @SWG\Schema(
 *         required={""},
 *         @SWG\Property(
 *              property="code",
 *              type="integer",
                example=400,
 *         ),
 *         @SWG\Property(
 *              property="msg",
 *              type="string",
                example="非法请求",
 *         ),
 *         
 *     )),

     * )     */

    //二级栏目接口
    public function getSonnav(){        if(request()->isAjax()){            $cate_id=input('id');            $data=Db::table('re_cate')->where('cate_pid',$cate_id)->field('cate_id,cate_name,cate_ison')->select();            if(!empty($data)){                return json(['code'=>200,'msg'=>'二级栏目返回成功','data'=>$data]);
            }else{                return json(['code'=>201,'msg'=>'无二级栏目']);
            }
            
        }else{            return json(['code'=>400,'msg'=>'非法请求']);
        }
        

    }     /**

     *@SWG\Post(path="/api/getarticlelist", tags={"Api"},

     *   summary="获取文章列表",

     *   description="根据栏目id获取文章列表(需要参数:栏目id,页码,一页显示文章数量)", 
      @SWG\Parameter(
     *         description="ajax请求要加上X-Requested-With:XMLHttpRequest头字段",
     *         format="string",
     *         in="header",
     *         name="X-Requested-With",
     *         required=true,
     *         type="string",
               default="XMLHttpRequest",
     *         
     *     ),  
     *   @SWG\Parameter(name="id",type="integer", required=true, in="formData",

     *     description="栏目id"

     *   ),     
     @SWG\Parameter(name="p",type="integer", required=true, in="formData",

     *     description="页码"

     *   ), 
       @SWG\Parameter(name="num",type="integer", required=true, in="formData",

     *     description="每页文章数量"

     *   ),      
         @SWG\Response(response="200", description="操作成功", @SWG\Schema(
 *         required={""},
 *         @SWG\Property(
 *              property="code",
 *              type="integer",
                example=200,
 *         ),
 *         @SWG\Property(
 *              property="msg",
 *              type="string",
                example="文章列表返回成功",
 *         ),
            @SWG\Property(
 *              property="data",
 *              type="object",
                example="{total:null,per_page:5,current_page:1,last_page:null,data:[{ar_id:1,cate_id:10,ar_title:'文章标题一',ar_keywords:'文章关键字',ar_pic:'url',ar_content:'文章内容',ar_ison:1}]}",
 *         ),
 *         
 *     )),
         @SWG\Response(response="201", description="数据为空", @SWG\Schema(
 *         required={""},
 *         @SWG\Property(
 *              property="code",
 *              type="integer",
                example=201,
 *         ),
 *         @SWG\Property(
 *              property="msg",
 *              type="string",
                example="数据为空!",
 *         ),
 *         
 *     )),
         @SWG\Response(response="400", description="非法请求,不是ajax请求", @SWG\Schema(
 *         required={""},
 *         @SWG\Property(
 *              property="code",
 *              type="integer",
                example=400,
 *         ),
 *         @SWG\Property(
 *              property="msg",
 *              type="string",
                example="非法请求",
 *         ),
 *         
 *     )),

     * )     */
    //指定栏目文章列表(需要参数:栏目id,页码,一页显示文章数量)
    /*
    返回json格式
        {
    "code": 200,
    "msg": "文章返回成功",
    "data": {
        "total": null,
        "per_page": "1",
        "current_page": 1,
        "last_page": null,
        "data": [
            {
                "ar_id": 1,
                "cate_id": 10,
                "ar_title": "title",
                "ar_keywords": "k,e,y",
                "ar_pic": "public/static/uploads/20190902\\98edeb3d27fe4342da8b07d5ae3e98de.jpg",
                "ar_content": "<p>内容<br/></p>",
                "ar_ison": 1
            }
        ]
    }
}    */
    public function getArticlelist(){            if(request()->isAjax()){            $cate_id=input('id');            $page=input('p');            $number=input('num');            $data=Db::table('re_article')->where('cate_id',$cate_id)->paginate($number,true,['page'=>$page]);            if(!empty($data)){                
                return json(['code'=>200,'msg'=>'文章返回成功','data'=>$data]);
            }else{                return json(['code'=>201,'msg'=>'没有数据了']);
            }
            
        }else{            return json(['code'=>400,'msg'=>'非法请求']);
        }
    }    /**

     *@SWG\Post(path="/api/getarticlecontent", tags={"Api"},

     *   summary="获取文章内容",

     *   description="根据文章id获取文章信息", 
      @SWG\Parameter(
     *         description="ajax请求要加上X-Requested-With:XMLHttpRequest头字段",
     *         format="string",
     *         in="header",
     *         name="X-Requested-With",
     *         required=true,
     *         type="string",
               default="XMLHttpRequest",
     *         
     *     ),  
     *   @SWG\Parameter(name="id",type="integer", required=true, in="formData",

     *     description="文章id"

     *   ),     
         @SWG\Response(response="200", description="操作成功", @SWG\Schema(
 *         required={""},
 *         @SWG\Property(
 *              property="code",
 *              type="integer",
                example=200,
 *         ),
 *         @SWG\Property(
 *              property="msg",
 *              type="string",
                example="文章返回成功",
 *         ),
            @SWG\Property(
 *              property="data",
 *              type="object",
                example="{ar_id:1,ar_title:'文章1',ar_pic:'url',ar_keywords:'文章关键字',ar_content:'文章内容',ar_ison:1}",
 *         ),
 *         
 *     )),
         @SWG\Response(response="201", description="数据为空", @SWG\Schema(
 *         required={""},
 *         @SWG\Property(
 *              property="code",
 *              type="integer",
                example=201,
 *         ),
 *         @SWG\Property(
 *              property="msg",
 *              type="string",
                example="数据为空!",
 *         ),
 *         
 *     )),
         @SWG\Response(response="400", description="非法请求,不是ajax请求", @SWG\Schema(
 *         required={""},
 *         @SWG\Property(
 *              property="code",
 *              type="integer",
                example=400,
 *         ),
 *         @SWG\Property(
 *              property="msg",
 *              type="string",
                example="非法请求",
 *         ),
 *         
 *     )),

     * )     */
    //获取指定文章内容
     public function getArticlecontent(){        if(request()->isAjax()){            $ar_id=input('id');            $data=Db::table('re_article')->where('ar_id',$ar_id)->find();            if(!empty($data)){                return json(['code'=>200,'msg'=>'文章返回成功','data'=>$data]);
            }else{                return json(['code'=>201,'msg'=>'无此文章']);
            }
            
        }else{            return json(['code'=>400,'msg'=>'非法请求']);
        }
        

    }



}


最新回复 (0)
发新帖