1、基于反射机制:实现注释生成文档
实现注释生成文档,主要是依赖反射机制获得成员函数的注释,然后基于注释的规范风格,进行参数切割(不建议使用正则表达式,因为效率太低),然后生成对应的html结构。
生成文档需要对注释风格编写是统一,并且规范才有可能实现,一旦不规范注释,就有可能生成错误。
具体的案例代码如下:
<?php
# 测试用的A类
class TestA {
/**
* 尼妹的
* @author 小黄牛
* @version v1.0.0.1
* @deprecated v1.0.9.* 版本后弃用
* @global 无
* @todo 后期这个函数需要优化到神一样的执行速度
* @param string $name 打死你
* @param string $name 打死你
* @param string $name 打死你
* @return void
*/
public function orderBackA() {}
/**
* 你哥的
* 这是一个给小黄牛用的函数,哈哈,不服你来打我啊
*
* @author 小黄牛
* @version v1.0.0.1
* @deprecated v1.0.9.* 版本后弃用
* @global 无
* @todo 后期这个函数需要优化到神一样的执行速度
* @param string $name 打死你
* @param string $name 打死你
* @param string $name 打死你
* @return void
*/
private function orderBackB() {}
}
# 文档生成类
class WordApi{
private $_obj_Public;
private $_obj_Private;
private $_obj_Protected;
private $_wordData;
private $_length = 0;
private $_wordGroup = [
'@author' => '作者',
'@version' => '版本',
'@deprecated' => '废弃说明',
'@global' => '全局变量',
'@todo' => '优化建议',
'@param' => '参数',
'@return' => '返回值',
];
/**
* 自动反射类
*
* @param string $className 类名
*/
public function __construct($className) {
# 使用ReflectionClass类
$class = new ReflectionClass($className);
# 获得成员函数
$this->_obj_Public = $class->getMethods(ReflectionMethod::IS_PUBLIC);
$this->_obj_Private = $class->getMethods(ReflectionMethod::IS_PRIVATE);
$this->_obj_Protected = $class->getMethods(ReflectionMethod::IS_PROTECTED);
# 自动触发解析
$this->getFunction();
$this->getNotes();
}
/**
* 反射类下面的所有成员函数名称
*/
private function getFunction() {
# 读取不同权限下的方法名称
foreach ($this->_obj_Public as $method) {
$this->_wordData[$this->_length]['obj'] = $method;
$this->_wordData[$this->_length]['class'] = $method->class;
$this->_wordData[$this->_length]['name'] = $method->name;
$this->_wordData[$this->_length]['auto'] = ['控制权限', 'public'];
$this->_length++;
}
foreach ($this->_obj_Private as $method) {
$this->_wordData[$this->_length]['obj'] = $method;
$this->_wordData[$this->_length]['class'] = $method->class;
$this->_wordData[$this->_length]['name'] = $method->name;
$this->_wordData[$this->_length]['auto'] = ['控制权限', 'private'];
$this->_length++;
}
foreach ($this->_obj_Protected as $method) {
$this->_wordData[$this->_length]['obj'] = $method;
$this->_wordData[$this->_length]['class'] = $method->class;
$this->_wordData[$this->_length]['name'] = $method->name;
$this->_wordData[$this->_length]['auto'] = ['控制权限', 'protected'];
$this->_length++;
}
}
/**
* 解析成员函数对应的注释内容
*/
private function getNotes() {
foreach ($this->_wordData as $key=>$val) {
# 获得成员函数对应的注释内容
$note = $val['obj']->getDocComment();
# 删除头尾标记(这里的第三个换行删除很重要)
$note = str_replace(['/**', '*/', '
'], '', $note);
$note = explode(' *', $note);
# 删除为空数组并更新键名索引
$note = array_values(array_filter($note));
foreach ($note as $k=>$v) {
foreach ($this->_wordGroup as $kk=>$vv) {
if (strrpos($v, $kk) !== false) {
unset($this->_wordData[$key]['obj']); // 删除操作对象
$name = str_replace('@', '', $kk);
$this->_wordData[$key][$name][0] = $vv;
$word = str_replace(" $kk ", '', $v);
# 对一些标记元做特殊处理
if (strrpos($v, '@param') !== false) {
$array = explode(' ', $word);
$this->_wordData[$key][$name][1][$k] = $array;
} else {
$this->_wordData[$key][$name][1] = $word;
}
} else {
if ($k == 0) {
$this->_wordData[$key]['title'][0] = '标题';
$this->_wordData[$key]['title'][1] = $v;
} else if ($k == 1) {
$this->_wordData[$key]['des'][0] = '详情';
if (strrpos($v, '@') === false) {
$this->_wordData[$key]['des'][1] = $v;
} else {
$this->_wordData[$key]['des'][1] = '';
}
}
}
}
}
}
}
/**
* 生成文档
*/
public function makeWord() {
$table = "<br/>函数规范:<hr/><table><tr><td width='150'>标记元</td><td width='120'>说明</td><td>详细</td></tr>";
$html = '';
foreach ($this->_wordData as $key=>$val) {
foreach ($val as $k=>$v) {
if ($k == 'class') {
$html .= "<h2>函数路径:$v -> ";
} else if ($k == 'name') {
$html .= "$v();</h2><hr/>";
} else if ($k == 'auto') {
$html .= '<h3>'.$v[0].':'.$v[1].'<h3/>';
} else if ($k == 'title') {
$html .= '<h3>'.$v[0].':'.$v[1].'<h3/>';
if (empty($val['des'])) {
$html .= $table;
}
} else if ($k == 'des') {
$html .= '<h3>'.$v[0].':'.$v[1].'<h3/>'.$table;
} else if ($k != 'param') {
$html .= '<tr><td>@'.$k.'</td><td>'.$v[0].'</td><td>'.$v[1].'</td></tr>';
}
}
$html .= '</table>';
if (!empty($val['param'])) {
$html .= "<br/>函数参数:<hr/><table><tr><td width='150'>变量名</td><td width='120'>类型</td><td>说明</td></tr>";
foreach ($val['param'][1] as $k=>$v) {
$html .= '<tr><td>'.$v[1].'</td><td>'.$v[0].'</td><td>'.$v[2].'</td></tr>';
}
$html .= '</table><hr/><br/>';
}
}
echo $html;
}
}
# 使用demo
$obj = new WordApi('TestA');
$obj->makeWord();