新出炉的没眼看的接口文档生成工具(如果这也叫工具的话)
<?php
//+------------------------------------------------------------------------------------------------
//| 生如夏花,望能璀璨绽放
//+------------------------------------------------------------------------------------------------
//| Author:moyuu <janmas@126.com>
//+------------------------------------------------------------------------------------------------
//|
//+------------------------------------------------------------------------------------------------
/*
* 根据Yii框架写的
* 类名 xxxController(其中的Controller为必须可根据自个儿的情况定)
* 方法名 actionXxx(其中的action为必须可根据自个儿的情况定)
*
* function注释格式
*
* @desc 测试
* @method get
* @param integer post id 测试
* @param integer post id 测试
* @param integer post id 测试
* @return array
*
* 有一个大BUG没有驼峰的处理 。。 找时间封个类耍耍吧 这个版本的就放着吧
*
*/
//工作目录
$workDir = dirname(dirname(__FILE__)) . '/api/controllers/';
// 基类文件
$baseControllerFile = dirname(dirname(__FILE__)) . '/api/controllers/ApiController.php';
$baseControllerFileInfo = pathinfo($baseControllerFile);
// 获取描述的正则
$descPartten = "/@desc(.*)?/";
//获取请求方式的
$methodPartten = "/@method(.*)?/";
//获取参数的正则
$paramPartten = "/@param\s(.*)\r\n?/";
//获取类文件的命名空间
function getNamespace($file){
//获取命名空间的正则
$namespacePattern = '/(.*)?namespace\s(.*)?;/';
$namespace = '';
$fileHandle = fopen($file,'r');
while(empty($namespace)){
$content = fgets($fileHandle);//逐行读取(感觉一次读多行更好反正namespace都在最前面)
if(preg_match($namespacePattern,$content,$namespace)){
$namespace = array_pop($namespace);
}else{
$namespace = '';
}
}
fclose($fileHandle);
return $namespace;
}
$document = [];//存放需要生成文档的数据
$files = glob($workDir . '*.php');
foreach($files as $file){
$fileInfo = pathinfo($file);
if($fileInfo === $baseControllerFileInfo){
//排除基类
continue;
}
$controller = str_replace('Controller','',$fileInfo['filename']);//获取控制器名称组装url用
$className = getNamespace($file) . '\\' . $fileInfo['filename'];//获取类名实例化反射类用
$reflectionClass = new ReflectionClass($className);
$methods = $reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC);
foreach($methods as $method){
if(strpos($method->name,'action') === false){
//规定不包含action的方法不对外开放(根据Yii框架写的)
continue;
}
$methodName = str_replace('action','',$method->name);
$doc = $method->getDocComment();
$parameter = [];
if(preg_match($descPartten,$doc,$desc)){
if(!empty($desc)){
$desc = array_pop($desc);
}
}else{
$desc = ' ';
}
if(preg_match($methodPartten,$doc,$httpMethod)){
$httpMethod = array_pop($httpMethod);
}else{
$httpMethod = ' ';
}
if(preg_match_all($paramPartten,$doc,$parameter)){
//咳咳 这一串处理注释里的@param的
if(!empty($parameter)){
$parameter = array_pop($parameter);
$parameter = array_map(function($aaa){
if(empty($aaa)){
return [];
}
$aaa = explode(' ' ,$aaa);
reset($aaa);
return [
'type' => current($aaa),
'method' => strtolower(next($aaa)),
'name' => next($aaa),
'desc' => next($aaa)
];
},$parameter);
}
}else{
$parameter = [];
}
//把需要的东西放进去
$document[$fileName][] = [
'url' => '\\' . strtolower($controller) . '\\' . strtolower($methodName),
'method' => $httpMethod,
'desc' => $desc,
'parameter' => $parameter,
'className' => $className,
];
}
}
$writeContent = '';
//组装文档内容并写入
foreach($document as $key=> $v){
$writeContent .= "### " . $key . " \r\n";
foreach($v as $value){
$writeContent .= "#### 描述\r\n";
$writeContent .= "- `" . $value['desc'] . "`\r\n\r\n";
$writeContent .= "#### 请求地址\r\n";
$writeContent .= "- `" . $value['url'] . "`\r\n\r\n";
$writeContent .= "#### 请求方式\r\n";
$writeContent .= "- ` " . $value['method'] . "`\r\n\r\n";
if(!empty($value['parameter'])) {
$writeContent .= "#### 请求参数\r\n";
$writeContent .= "|名称|类型|描述|\r\n";
$writeContent .= "|:--|:--|:--|\r\n";
foreach ($value['parameter'] as $p) {
if($p){
$writeContent .= "|" . $p['name'] . "|" . $p['type'] . "|" . $p['desc'] . "|\r\n";
}
continue;
}
}
$writeContent .= "--- \r\n\r\n";
}
}
file_put_contents('./test.md',$writeContent);