hyperf配合hyperf-swagger一条命令根据响应体生成生成swagger文档

文章目录

<?php

declare(strict_types=1);
/**
 * This file is part of hyperf-tt.
 *
 * @link     https://github.com/zhaohao19941221/hyperf-tt
 * @document https://github.com/zhaohao19941221/hyperf-tt.git
 */
namespace AppCommand;

use HyperfCommandAnnotationCommand;
use HyperfCommandCommand as HyperfCommand;
use HyperfDbConnectionDb;
use PsrContainerContainerInterface;
use SymfonyComponentConsoleInputInputArgument;
use SymfonyComponentConsoleInputInputOption;

/**
 * @Command
 */
class SwaggerCommand extends HyperfCommand
{
    /**
     * @var ContainerInterface
     */
    protected container;

    // 表注释对应
    protectedswaggerTable;

    // 请求方式
    protected swaggerMethod;

    // url路径
    protectedswaggerPath;

    // 标签
    protected swaggerTag;

    // 概要
    protectedswaggerSummary;

    // 描述
    protected swaggerDescription;

    // query格式数据
    protectedswaggerQuery;

    // 请求 json 数据类型
    protected swaggerRequestBody;

    // 响应 json 数据类型
    protectedswaggerResponse;

    /**
     * 执行的命令行.
     *
     * @var string
     */
    protected name = 'swagger:format';

    public function __construct(ContainerInterfacecontainer)
    {
        this->container =container;
        parent::__construct();
    }

    public function configure()
    {
        parent::configure();
        this->setHelp('示例:php bin/hyperf.php swagger:format Post '{"errcode":0,"errmsg":"success","data":{"token":"666"}}'');this->setDescription('swagger mode生成');
        this->addArgument('method', InputArgument::OPTIONAL, '请求方式', 'Get');this->addArgument('response', InputArgument::OPTIONAL, '响应 json 数据类型');
        this->addArgument('table', InputArgument::OPTIONAL, '自动填充数据表');this->addOption('path', 'P', InputOption::VALUE_OPTIONAL, 'url路径');
        this->addOption('tag', 'T', InputOption::VALUE_OPTIONAL, '标签');this->addOption('summary', 'S', InputOption::VALUE_OPTIONAL, '概要');
        this->addOption('description', 'D', InputOption::VALUE_OPTIONAL, '描述');this->addOption('query', 'Q', InputOption::VALUE_OPTIONAL, 'query格式数据');
        this->addOption('request', 'R', InputOption::VALUE_OPTIONAL, '请求 json 数据类型');
    }

    public function handle()
    {this->swaggerTable = this->input->getArgument('table');this->swaggerMethod = ucfirst(strtolower(this->input->getArgument('method')));this->swaggerPath = this->getSwaggerPath(this->input->getOption('path'));
        this->swaggerTag =this->getSwaggerTag(this->input->getOption('tag'));this->swaggerSummary = this->getSwaggerSummary(this->input->getOption('summary'));
        this->swaggerDescription =this->getSwaggerDescription(this->input->getOption('description'));this->swaggerQuery = this->getSwaggerParameter(this->input->getOption('query'));
        this->swaggerRequestBody =this->getSwaggerRequestBody(this->input->getOption('request'));this->swaggerResponse = this->getSwaggerResponse(this->input->getArgument('response'));
        echo this->getSwaggerModel();
    }

    /**
     * 获取 swagger 结构.
     */
    public function getSwaggerModel()
    {doc = PHP_EOL . PHP_EOL;
        header =this->swaggerPath . this->swaggerTag .this->swaggerSummary . this->swaggerDescription;header = trim(header, PHP_EOL);body = this->swaggerQuery .this->swaggerRequestBody . this->swaggerResponse;body = trim(body, PHP_EOL);doc .= <<<eof
    /**
     * @OA{this->swaggerMethod}(
{header}
     *     operationId="",
     *     @OAParameter(name="Authorization", in="header", description="jwt签名", required=true,
     *         @OASchema(type="string", default="Bearer {{Authorization}}")
     *     ),
{body}
     * )
     */
eof;doc .= PHP_EOL . PHP_EOL;
        return doc;
    }

    /**
     * 获取路径数据.
     * @param null|stringpath 路径
     */
    public function getSwaggerPath(?string path): string
    {doc = <<<eof
     *     path="{path}",
eof;doc .= PHP_EOL;
        return doc;
    }

    /**
     * 获取标签数据.
     * @param null|stringtag 标签
     */
    public function getSwaggerTag(?string tag): string
    {doc = <<<eof
     *     tags={"{tag}"},
eof;doc .= PHP_EOL;
        return doc;
    }

    /**
     * 获取概要数据.
     * @param null|stringsummary 概要
     * @return string 概要格式数据
     */
    public function getSwaggerSummary(?string summary): string
    {doc = <<<eof
     *     summary="{summary}",
eof;doc .= PHP_EOL;
        return doc;
    }

    /**
     * 获取描述数据.
     * @param null|stringdescription 描述
     * @return string 描述格式数据
     */
    public function getSwaggerDescription(?string description): string
    {doc = <<<eof
     *     description="{description}",
eof;doc .= PHP_EOL;
        return doc;
    }

    /**
     * query 参数拼接.
     */
    public function getSwaggerParameter(?stringparameter): string
    {
        if (! parameter) {
            return <<<'eof'
eof;
        }
        parse_str(parameter, output);
        if (!parameter) {
            return <<<'eof'
eof;
        }
        doc = '';
        foreach (output as k =>v) {
            type =this->gettype(v);doc .= <<<eof
     *     @OAParameter(name="{k}", in="query", description="",
     *         @OASchema(type="{type}", default="{v}")
     *     ),
eof;doc .= PHP_EOL;
        }
        return doc;
    }

    /**
     * 获取请求 JsonContent 数据.
     */
    public function getSwaggerRequestBody(?stringrequestBody): string
    {
        if (! requestBody) {
            return <<<'eof'
eof;
        }requestBody = this->constructSwaggerDoc(requestBody);
        doc = <<<eof
     *     @OARequestBody(description="请求body",
     *         @OAJsonContent(type="object",
{requestBody}
     *         )
     *     ),
eof;
        doc .= PHP_EOL;
        returndoc;
    }

    /**
     * 获取响应 JsonContent 数据.
     * @param null|string response 响应json
     */
    public function getSwaggerResponse(?stringresponse): string
    {
        comment =this->getColumnComment(this->swaggerTable);comment['errcode'] = '错误码';
        comment['errmsg'] = '错误信息';comment['data'] = '返回数据';
        if (! response) {
            return <<<eof
     *     @OAResponse(response="200", description="响应信息返回",
     *         @OAJsonContent(type="object",
     *             @OAProperty(property="errcode", type="integer", description="{comment['errcode']}"),
     *             @OAProperty(property="errmsg", type="string", description="{comment['errmsg']}"),
     *             @OAProperty(property="data", type="object", description="{comment['data']}",
     *                  @OAProperty(property="example", type="string", description="例子",
     *             )
     *         )
     *     )
eof;
        }
        response =this->constructSwaggerDoc(response,comment);
        return <<<eof
     *     @OAResponse(response="200", description="响应信息返回",
     *         @OAJsonContent(type="object",
{response}
     *         )
     *     )
eof;
    }

    /**
     * 检测是否为有序数据.
     * @param mixedarray
     * @return string array 有序数据 object 无序数组
     */
    public function checkIsArray(array): string
    {
        if (! is_array(array)) {
            return 'string';
        }
        num = count(array);
        for (i = 0;i < num; ++i) {
            if (isset(array[i])) {
                continue;
            }
            return 'object';
        }
        return 'array';
    }

    /**
     * 构造 JsonContent 数据.
     * @param array|string data json格式字符串数据|数组数据
     * @param arraycomment 注释
     * @param string placeholder 占位空格数量
     * @param stringpropertyType 数据格式
     * @return string JsonContent格式数据
     */
    private function constructSwaggerDoc(data, arraycomment = [], string placeholder = '', stringpropertyType = 'Property'): string
    {
        if (! data) {
            return <<<'eof'
eof;
        }data = is_array(data) ?data : json_decode(data, true);required = this->arrayToJsonObject(data);
        doc = '';
        if (propertyType == 'Items') {
            doc .= <<<eof
     *             {placeholder}@OAItems(
eof;
            doc .= PHP_EOL;placeholder .= '    ';
        }
        doc .= <<<eof
     *             {placeholder}required={required},
eof;doc .= PHP_EOL;
        foreach (data ask => v) {description = comment[k] ?? null;
            type =this->gettype(v);
            if (in_array(type, ['object', 'array'])) {
                if (isset(v[0]) || empty(v)) {
                    if (isset(v[0]) && is_array(v[0])) {
                        doc .= <<<eof
     *             {placeholder}@OAProperty(property="{k}", type="array", description="{description}",
eof;
                        doc .= PHP_EOL;newPlaceholder = placeholder . '    ';doc .= this->constructSwaggerDoc(v[0], comment,newPlaceholder, 'Items');
                    } else {
                        doc .= <<<eof
     *             {placeholder}@OAProperty(property="{k}", type="array", description="{description}",
     *                 {placeholder}@OAItems()
eof;doc .= PHP_EOL;
                    }
                } else {
                    doc .= <<<eof
     *             {placeholder}@OAProperty(property="{k}", type="object", description="{description}",
eof;
                    doc .= PHP_EOL;newPlaceholder = placeholder . '    ';doc .= this->constructSwaggerDoc(v, comment,newPlaceholder);
                }
                if (isset(v[0]) || empty(v)) {
                    doc .= <<<eof
     *             {placeholder}),
eof;
                } else {
                    doc .= <<<eof
     *             {placeholder}),
eof;
                }
                doc .= PHP_EOL;
            } else {doc .= <<<eof
     *             {placeholder}@OAProperty(property="{k}", type="{type}", description="{description}"),
eof;
                doc .= PHP_EOL;
            }
        }
        if (propertyType == 'Items') {
            placeholder = substr(placeholder, 0, -4);
            doc .= <<<eof
     *             {placeholder}),
eof;
            doc .= PHP_EOL;
        }
        if (!placeholder) {
            doc = trim(doc, PHP_EOL);
        }
        return doc;
    }

    /**
     * 获取数据类型.
     * @paramvalue
     */
    private function gettype(value): string
    {type = (string) gettype(value);
        switch (type) {
            case 'array':
                result =this->checkIsArray(value);
                break;
            case 'integer':
            case 'boolean':
            case 'string':result = type;
                break;
            default:result = 'string';
                break;
        }
        return result;
    }

    /**
     * json数组格式转化为对象格式.
     * @param arrayarray 有序数组
     */
    private function arrayToJsonObject(array array): string
    {jsonObject = trim(json_encode(array_keys(array)), '[');
        return '{' . trim(jsonObject, ']') . '}';
    }

    /**
     * 获取数据表字段描述.
     */
    private function getColumnComment(?string tables): array
    {
        if (empty(tables)) {
            return [];
        }

        tablesList = explode(',',tables);
        if (! tablesList) {
            return [];
        }haveKey = [];
        list = [];
        foreach (tablesList as v) {sql = "SELECT COLUMN_NAME,column_comment FROM INFORMATION_SCHEMA.Columns WHERE table_name = '{v}'";comment = Db::select(sql);
            // 需要保持字段名唯一,唯一字段才会保留
            foreach (comment as v) {
                // 判断 字段名 是否出现过
                if (in_array(v['COLUMN_NAME'], haveKey)) {
                    continue;
                }
                // 判断  字段名 是否存在,存在的情况需要移除,并加入到 haveKey 数组
                if (isset(list[v['COLUMN_NAME']])) {
                    unset(list[v['COLUMN_NAME']]);
                    array_push(haveKey, v['COLUMN_NAME']);
                }list[v['COLUMN_NAME']] =v['column_comment'];
            }
        }
        return $list;
    }
}

php bin/hyperf.php swagger:format Post '{"errcode":0,"errmsg":"success","data":{"token":"666"}}'

hyperf配合hyperf-swagger一条命令根据响应体生成生成swagger文档

zhaohao

大家好,欢迎来到赵豪博客!赵豪,94年生人,PHP程序员一枚,因为对PHP开发有着相对比较浓厚的兴趣,所以现在从事着PHP程序员的工作。 今天再次开通这个博客,这里将记录我的职业生涯的点点滴滴,感谢来访与关注!如果我的博客能给您带来一些帮助那真是一件非常荣幸的事情~

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

微信扫一扫

微信扫一扫

微信扫一扫,分享到朋友圈

hyperf配合hyperf-swagger一条命令根据响应体生成生成swagger文档
返回顶部

显示

忘记密码?

显示

显示

获取验证码

Close