wangzd/laravel-apidoc-generator

从您的Laravel应用程序生成美观的API文档

v0.1 2023-05-09 07:47 UTC

This package is not auto-updated.

Last update: 2024-09-25 11:57:32 UTC


README

https://github.com/mpociot/laravel-apidoc-generator
本项目是在以上项目基础之上修改

提示:继续采用request文件的验证规则作为bodyParameters,mpociot/laravel-apidoc-generator已经放弃该做法

修改的清单

  • 生成collection_swagger.json 需要加 --swaggerCollection 参数
public_path('docs/collection_swagger.json')

可以供yapi自动导入

  • request相关的参数都在request验证类中体现,需要继承Mpociot\ApiDoc\Request\BaseRequest
<?php

namespace Mpociot\ApiDoc\Request;

use Illuminate\Foundation\Http\FormRequest;

/**
 *
 *
 * Class    BaseRequest
 *
 * describe:
 *
 * ===========================================
 * Copyright  2020/9/28 2:25 下午 517013774@qq.com
 *
 * @resource  BaseRequest
 * @license   MIT
 * @package   Mpociot\ApiDoc\Request
 * @author    Mz
 */
abstract class BaseRequest extends FormRequest implements RequestInterface
{
   
}
<?php

namespace Mpociot\ApiDoc\Request;

interface RequestInterface
{

    /**
     * 路由验证规则
     * tips: 生成文档时required|sometimes|regex等规则会被屏蔽掉,原因是:需要以路由参数为准
     * @return array
     */
    public function routeRules(): array;

    /**
     * header验证规则
     * @return array
     */
    public function headerRules(): array;

    /**
     *
     * getSwaggerContentType
     * 默认值:application/json
     *
     * @return string
     */
    public function getSwaggerContentType(): string;

}
  • 规则校验新增 describe 规则
public function rules()
{
        return [
            'file' => 'required|file|describe:这里写描述.',
        ];
}

describe只对生成文档有效,不作为laravel校验规则

  • 如果字段中文名能作为描述:上述规则也可以使用laravel验证类的attributes()方法
<?php

namespace App\Http\Controllers\Admin\Requests;

use SalesTenant\Commons\Requests\Request;

/**
 *
 *
 * Class    UserIndexRequest
 *
 * describe:用户管理列表的验证码类
 *
 * ===========================================
 * Copyright  2020/9/27 4:11 下午 517013774@qq.com
 *
 * @resource  UserIndexRequest
 * @license   MIT
 * @package   App\Http\Controllers\Admin\Requests
 * @author    Mz
 */
class UserIndexRequest extends Request
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }


    /**
     * 获取已定义验证规则的错误消息。
     *
     * @return array
     */
    public function messages()
    {
        return [
            'regex' => ':attribute格式不正确.',
            'string' => ':attribute为字符串.',
            'integer' => ':attribute为数字,',
            'in' => ':attribute只能是:values其中之一.',
        ];
    }

    /**
     *
     * attributes
     *
     * @return array
     */
    public function attributes()
    {
        return [
            'keyword' => '关键字',
            'name' => '用户姓名',
            'mobile' => '手机',
            'email' => '邮箱',
            'is_admin' => '搜索管理员'
        ];
    }

    /**
     * 请求体验证规则
     * @return array
     */
    public function rules(): array
    {
        return [
            'keyword' => 'sometimes|regex:/^[0-9]+$/|describe:搜索:姓名、邮箱、手机等字段.',
            'name' => 'sometimes|describe:搜索姓名',
            'mobile' => 'sometimes|describe:搜索手机',
            'email' => 'sometimes|describe:搜索邮箱',
            'is_admin' => 'sometimes|integer|in:0,1|describe:搜索是否是管理员',
        ];
    }

    /**
     * 路由验证规则
     * tips: 生成文档时required|sometimes|regex等规则会被屏蔽掉,原因是:需要以路由参数为准
     * @return array
     */
    public function routeRules(): array
    {
        return [
            'limit' => "integer|describe:每页条数",
            'page' => "integer|describe:当前分页",
            'sort' => "string|describe:排序字段",
            'order' => "string|in:DESC,ASC|describe:排序字段",
        ];
    }
    public function headerRules(): array
    {
        return [
            'Content-Type' => "required|string|describe:媒体",
            'Cookie' => 'required|string|describe:登录时需要的cookie.',
        ];
    }

}

describe优先级大于attributes()方法

  • 使用@responseTransformer标签 写 response
/**
     *
     * 后台日志列表
     *
     * describe:后台日志管理列表
     *
     * @responseTransformer App\Transformers\Admin\Log\IndexTransformer
     *
     * @param LogIndexRequest $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Exception
     */
    public function index(LogIndexRequest $request)
    {
        $this->getRouteParam($request);
        $data = app(AdminOperate::class)->search($request->all(),
            [$this->routeParam['sort'] => $this->routeParam['order']],
            $this->routeParam['page'],
            $this->routeParam['limit']);
        return $this->paginate($data);
    }
<?php

namespace App\Transformers\Admin\Log;

use Mpociot\ApiDoc\Transformer\BaseTransformer;

/**
 *
 *
 * Class    IndexTransformer
 *
 * describe:
 *
 * ===========================================
 * Copyright  2020/9/27 3:21 下午 517013774@qq.com
 *
 * @resource  IndexTransformer
 * @license   MIT
 * @package   App\Transformers\Admin\Log
 * @author    Mz
 */
class IndexTransformer extends BaseTransformer
{
    /**
     * 该转换器中字段可能涉及到的表
     * 如果为空,则会取整个库
     * @var array
     */
    protected $tables = [];

    /**
     * 自定义字段注释
     * 当然你也可以通过 config('apidoc.columnComments') 去设置一些通用的字段注释
     * 优先级为:1:配置config('apidoc.columnComments');2:属性$columnComments;3:$tables设置的表字段注释;4:整个库
     * @var array
     */
    protected $columnComments = [];

    /**
     *
     * response
     *
     * describe:
     *
     * @return mixed
     */
    public function response()
    {
        $res = <<<RES
{"totalPages":147,"totalCount":1462,"page":1,"limit":10,"count":10,"firstPage":true,"lastPage":false,"hasPrePage":false,"hasNextPage":true,"prePage":0,"nextPage":2,"items":[{"id":77392,"user_id":"0","operator":"\u7ba1\u7406\u5458","url":"\/api\/sales\/tenant\/shop\/config","method":"POST","request_data":"{\"shop_tenant_id\":\"98\",\"shop_config\":{\"hash_key\":\"kjN3S3r7yahJZ6wna7DRXZj48RTBXjDF2\"}}","md5":"31c51ede3ddb7fcc924075207e99d7f4","created_at":"2020-09-10 16:27:29","updated_at":"2020-09-10 16:27:29","deleted_at":null},{"id":77391,"user_id":"0","operator":"\u7ba1\u7406\u5458","url":"\/api\/sales\/tenant\/shop","method":"POST","request_data":"{\"source\":\"LWJ_SHOP\",\"name\":\"ddd\",\"tenant_code\":\"TEST08\"}","md5":"f9ff4d0215029eb40eae00224b3e8d09","created_at":"2020-09-10 16:27:21","updated_at":"2020-09-10 16:27:21","deleted_at":null},{"id":77390,"user_id":"0","operator":"\u7ba1\u7406\u5458","url":"\/api\/permission\/bindMenus","method":"PUT","request_data":"{\"id\":1,\"menuIds\":[]}","md5":"5c383d10b3f73a2da30603f584b72497","created_at":"2020-09-08 14:49:14","updated_at":"2020-09-08 14:49:14","deleted_at":null},{"id":77389,"user_id":"0","operator":"\u7ba1\u7406\u5458","url":"\/api\/sales\/user","method":"POST","request_data":"{\"mobile\":\"15982476445\"}","md5":"36e3471db1127c6d8c2b4b06a3b9a9f6","created_at":"2020-09-08 14:49:08","updated_at":"2020-09-08 14:49:08","deleted_at":null},{"id":77388,"user_id":"0","operator":"\u7ba1\u7406\u5458","url":"\/api\/sales\/user\/superAdmin","method":"POST","request_data":"{\"id\":\"e6b1934bddf84733bf1bb417b976105c\",\"is_admin\":0}","md5":"f0297ef6039e9a22aab17a86c9a4d1fa","created_at":"2020-09-08 14:49:05","updated_at":"2020-09-08 14:49:05","deleted_at":null},{"id":77387,"user_id":"0","operator":"\u7ba1\u7406\u5458","url":"\/api\/sales\/config","method":"PUT","request_data":"{\"sales_domain\":\"https:\/\/admin-sales-staging.liweijia.com:28043\",\"sales_oauth_client_id\":\"7aa8ca910e4e4726bb2afbeda283bdd1\",\"sales_oauth_client_secret\":\"ML8PQYRO\",\"sales_oauth_scope\":\"trust\",\"sales_sync\":\"1\",\"recipients\":\"zhoufengmin@liweijia.com|jiangzhiheng@liweijia.com|xuyesi@liweijia.com|liuminzhe@liweijia.com\",\"auto_retry_num\":\"5\"}","md5":"cd218015991a981232778df7d0c73688","created_at":"2020-09-08 14:48:46","updated_at":"2020-09-08 14:48:46","deleted_at":null},{"id":77386,"user_id":"0","operator":"\u7ba1\u7406\u5458","url":"\/api\/sales\/tenant\/import\/order","method":"POST","request_data":"{\"limit\":10,\"page\":1,\"tenant_code\":\"DSFPTCLOUD\",\"tenant_id\":123,\"sales_user_id\":\"ganwang0001\",\"mobile\":\"15777779003\",\"store_code\":\"AA0BBB76\",\"file\":\"\/upload\/templates\/1a5bed584172272a6438cecb49d4f20e.xlsx\",\"pwd\":\"UDlaV2FFUTlvcllWS0ZTWGs1TzQ5dz09\"}","md5":"cdd32781477204750eced9f3d43cfa93","created_at":"2020-09-08 14:48:30","updated_at":"2020-09-08 14:48:30","deleted_at":null},{"id":77385,"user_id":"0","operator":"\u7ba1\u7406\u5458","url":"\/api\/sales\/tenant\/import\/order","method":"POST","request_data":"{\"limit\":10,\"page\":1,\"tenant_code\":\"DSFPTCLOUD\",\"tenant_id\":123,\"sales_user_id\":\"ganwang0001\",\"mobile\":\"15777779003\",\"store_code\":\"AA0BBB76\",\"file\":\"\/upload\/templates\/1a5bed584172272a6438cecb49d4f20e.xlsx\",\"pwd\":\"UDlaV2FFUTlvcllWS0ZTWGs1TzQ5dz09\"}","md5":"cdd32781477204750eced9f3d43cfa93","created_at":"2020-09-08 14:47:26","updated_at":"2020-09-08 14:47:26","deleted_at":null},{"id":77384,"user_id":"0","operator":"\u7ba1\u7406\u5458","url":"\/api\/sales\/attachment\/excel","method":"POST","request_data":"{\"rename\":\"1\",\"type\":\"local\",\"folder\":\"templates\",\"file\":{}}","md5":"c6f4002c95f062961198cab600c3e861","created_at":"2020-09-08 14:47:24","updated_at":"2020-09-08 14:47:24","deleted_at":null},{"id":77383,"user_id":"0","operator":"\u7ba1\u7406\u5458","url":"\/api\/sales\/tenant\/import\/order","method":"POST","request_data":"{\"limit\":10,\"page\":1,\"tenant_code\":\"TEST06_710\",\"tenant_id\":184,\"sales_user_id\":\"ganwang0001\",\"mobile\":\"13800008989\",\"store_code\":\"HTQXL01\",\"file\":\"\/upload\/templates\/1a5bed584172272a6438cecb49d4f20e.xlsx\",\"pwd\":\"UDlaV2FFUTlvcllWS0ZTWGs1TzQ5dz09\"}","md5":"6dfde587d7b12ee5db01885a691f3a08","created_at":"2020-09-08 14:46:58","updated_at":"2020-09-08 14:46:58","deleted_at":null}]}
RES;
        return json_decode($res);
    }

}

建议

  • 为自己添加一些 Live Templates
命令	注释

@help	查看帮助   
@dt	data types(不清楚有哪些数据类型,参考)

参考:
https://blog.csdn.net/tu1091848672/article/details/78670602
  • 修改 PHP Class Doc Comment
/**
 *
 *
 * Class    ${NAME}
 * 
 * describe:
 *
 * ===========================================
 * Copyright  ${DATE} ${TIME} 517013774@qq.com
 *
 * @resource  ${NAME}
 * @license   MIT
 * @package   ${NAMESPACE}
 * @author    Mz
 */
 
 `@resource` 加上可以为接口分组
 

Laravel API文档生成器

从现有的Laravel路由自动生成API文档。请查看 示例文档

php artisan api:gen --routePrefix="settings/api/*"

image image codecov.io Scrutinizer Code Quality Build Status StyleCI Dependency Status

安装

您可以通过vcs的方式安装: 在composer.json中添加 repositories 属性

"repositories": [
  {
    "type": "vcs",
    "url": "https://github.com/MissZhou12345/laravel-apidoc-generator.git"
  }
]

然后添加:require-dev

"require-dev": {
    "mpociot/laravel-apidoc-generator": "dev-master"
}

您就可以拉取本项目了

使用以下命令通过composer安装此包

$ composer require mpociot/laravel-apidoc-generator

使用Laravel < 5.5?前往您的 config/app.php 并添加服务提供者

Mpociot\ApiDoc\ApiDocGeneratorServiceProvider::class,

使用Laravel < 5.4?使用版本 1.0!对于Laravel 5.4及以上版本,请使用2.0。

用法

要生成API文档,请使用 api:generate artisan命令。

$ php artisan api:generate --routePrefix="api/v1/*"

此命令将扫描您的应用程序路由,查找匹配 api/v1/* 的URI,并解析这些控制器方法和表单请求。例如

// API Group Routes
Route::group(array('prefix' => 'api/v1', 'middleware' => []), function () {
	// Custom route added to standard Resource
	Route::get('example/foo', 'ExampleController@foo');
	// Standard Resource route
	Route::resource('example', 'ExampleController');
});

可用命令选项

发布规则描述以进行自定义或翻译。

默认情况下,此包以英语返回描述。您可以通过发布包的语言文件来自定义和翻译文档输出。

$ php artisan vendor:publish

文件发布后,您可以通过重命名 en 文件夹并编辑 public/vendor/apidoc/resources/lang 中的文件来以您选择的语言自定义或翻译描述。

它是如何工作的?

此包使用以下资源生成API文档

控制器文档块

此包使用HTTP控制器文档块来创建目录表并显示API方法的描述。

在控制器之前使用@resource在文档块中很有用,因为它为该控制器中定义的所有方法在API文档中创建一个组(而不是在所有控制器的单个列表中列出每个方法),但使用@resource不是必需的。在@resource之后的简短描述应该是唯一的,以便允许锚点标签导航到该部分。可以包含一个更长的描述。

在每个您希望包含在API文档中的控制器方法上方,您应该有一个文档块。这应该包括一个唯一的简短描述作为第一项。可以添加一个可选的第二项以包含更多信息。这两个描述将以不同的格式出现在API文档中,如下所示。

/**
 * @resource Example
 *
 * Longer description
 */
class ExampleController extends Controller {

	/**
	 * This is the short description [and should be unique as anchor tags link to this in navigation menu]
	 *
	 * This can be an optional longer description of your API call, used within the documentation.
	 *
	 */
	 public function foo(){

	 }

结果

Doc block result

表单请求验证规则

为了显示API方法接受的参数列表,此包使用Laravel的 表单请求验证

public function rules()
{
    return [
        'title' => 'required|max:255',
        'body' => 'required',
        'type' => 'in:foo,bar',
        'thumbnail' => 'required_if:type,foo|image',
    ];
}

结果: Form Request

控制器方法文档块

可以覆盖响应的结果。这也会显示除GET之外的请求方法响应。

@transformer

使用transformer,您可以定义用于方法结果的处理程序。如果它找到处理程序,它将尝试下一部分来获取结果。第一个成功的将用于。

  1. 检查是否有transformermodel标签来定义模型
  2. 从modelfactory获取模型
  3. 如果参数是Eloquent模型,它将从数据库中加载第一个。
  4. 从类创建一个新实例
/**
 * @transformer \Mpociot\ApiDoc\Tests\Fixtures\TestTransformer
 */
public function transformerTag()
{
    return '';
}

@transformercollection

这与@transformer标签的想法相同,但有一点不同,它将生成返回一个包含两个项目的集合,而不是返回一个项目。

/**
 * @transformercollection \Mpociot\ApiDoc\Tests\Fixtures\TestTransformer
 */
public function transformerCollectionTag()
{
    return '';
}

@transformermodel

@transformermodel标签对于PHP 5.*是必需的,以获取模型。对于PHP 7,指定用于处理程序的模型是可选的。

@response

如果您明确想要指定函数的结果,可以在注释块中设置它。

/**
 * @response {
 *  data: [],
 *}
 */
public function responseTag()
{
    return '';
}

API响应

如果您的API路由接受GET方法,此包会尝试使用所有中间件禁用来调用API路由,以获取示例API响应。

如果您的API需要一个认证用户,您可以使用actAsUserId选项来指定一个用于执行这些API调用的用户ID。

$ php artisan api:generate --routePrefix="api/*" --actAsUserId=1

如果您不想自动执行API响应调用,请使用noResponseCalls选项。

$ php artisan api:generate --routePrefix="api/*" --noResponseCalls

注意:示例API响应与种子的数据配合使用效果最佳。

Postman集合

生成器会自动创建一个Postman集合文件,您可以将其导入到您的Postman应用中,以便进行更简单的API测试和使用。

如果您不想创建Postman集合,在生成API文档时请使用--noPostmanCollection选项。

截至Laravel 5.3,Postman集合中添加的默认基本URL将是您的Laravel config/app.php文件中找到的URL。这可能是https://。如果您想更改此设置,可以直接更新URL或将此配置值链接到您的环境文件,使其更加灵活(如下所示)

'url' => env('APP_URL', 'http://yourappdefault.app'),

如果您正在引用上面的环境设置,那么您应该确保您已经更新了您的.env文件以设置适当的APP_URL值。否则,您的Postman集合将使用默认值(http://yourappdefault.app)。

APP_URL=http://yourapp.app

修改生成的文档

如果您想修改生成的文档内容,请编辑生成的index.md文件。该文件的默认位置是:public/docs/source/index.md

编辑markdown文件后,使用api:update命令重建您的文档作为静态HTML文件。

$ php artisan api:update

作为可选参数,您可以使用--location告诉更新命令您的文档可以在哪里找到。

跳过单个路由

如果您想从匹配给定前缀的路由列表中跳过一个路由,您可以在不想记录的控制器方法上使用@hideFromAPIDocumentation标签。

进一步修改

此包使用Documentarian生成API文档。如果您想修改文档的CSS文件,或者只是想了解更多信息,请查看Documentarian指南

许可证

Laravel API文档生成器是免费软件,根据MIT许可证授权。