PHP Markdown 文档生成

wen PHP项目 1

我来帮你创建一个PHP Markdown文档生成工具,这个工具可以方便地将PHP代码转换为格式化的Markdown文档。

PHP Markdown 文档生成

完整实现方案

基础Markdown生成器类

<?php
/**
 * MarkdownDocumenter - PHP代码文档生成器
 * 
 * 自动从PHP源代码生成Markdown格式的文档
 */
class MarkdownDocumenter {
    /** @var string 生成的文档内容 */
    private $documentation = '';
    /** @var array 解析的类信息 */
    private $classInfo = [];
    /** @var array 函数信息 */
    private $functionInfo = [];
    /**
     * 从PHP文件生成Markdown文档
     * 
     * @param string $filePath PHP文件路径
     * @return string Markdown内容
     */
    public function generateFromFile($filePath) {
        if (!file_exists($filePath)) {
            return "错误: 文件不存在";
        }
        $content = file_get_contents($filePath);
        return $this->generateFromSource($content);
    }
    /**
     * 从源代码生成Markdown文档
     * 
     * @param string $source PHP源代码
     * @return string Markdown内容
     */
    public function generateFromSource($source) {
        $this->documentation = '';
        $this->classInfo = [];
        $this->functionInfo = [];
        // 提取PHP代码块
        preg_match_all('/<\?php(.*?)(?:\?>|$)/s', $source, $matches);
        foreach ($matches[1] as $phpCode) {
            $this->analyzeCode($phpCode);
        }
        $this->buildDocumentation();
        return $this->documentation;
    }
    /**
     * 分析PHP代码
     * 
     * @param string $code PHP代码
     */
    private function analyzeCode($code) {
        // 提取注释块
        preg_match_all('/\/\*\*(.*?)\*\//s', $code, $docBlocks, PREG_OFFSET_CAPTURE);
        // 提取类定义
        preg_match_all('/class\s+(\w+)(?:\s+extends\s+(\w+))?(?:\s+implements\s+([^{]+))?/i', $code, $classes, PREG_OFFSET_CAPTURE);
        // 提取接口定义
        preg_match_all('/interface\s+(\w+)/i', $code, $interfaces, PREG_OFFSET_CAPTURE);
        // 提取trait定义
        preg_match_all('/trait\s+(\w+)/i', $code, $traits, PREG_OFFSET_CAPTURE);
        // 提取函数定义
        preg_match_all('/function\s+(\w+)\s*\(([^)]*)\)/i', $code, $functions, PREG_OFFSET_CAPTURE);
        // 处理类
        if (!empty($classes[1])) {
            foreach ($classes[1] as $index => $class) {
                $className = $class[0];
                $line = $this->getLineNumber($code, $class[1]);
                $info = [
                    'name' => $className,
                    'line' => $line,
                    'extends' => isset($classes[2][$index][0]) ? $classes[2][$index][0] : null,
                    'implements' => isset($classes[3][$index][0]) ? $classes[3][$index][0] : null,
                    'methods' => [],
                    'properties' => []
                ];
                // 提取类的方法
                $this->extractMethods($code, $class[1], $info);
                // 提取类的属性
                $this->extractProperties($code, $class[1], $info);
                $this->classInfo[] = $info;
            }
        }
        // 处理接口
        if (!empty($interfaces[1])) {
            foreach ($interfaces[1] as $index => $interface) {
                $interfaceName = $interface[0];
                $line = $this->getLineNumber($code, $interface[1]);
                $info = [
                    'name' => $interfaceName,
                    'line' => $line,
                    'type' => 'interface',
                    'methods' => []
                ];
                $this->extractMethods($code, $interface[1], $info);
                $this->classInfo[] = $info;
            }
        }
        // 处理trait
        if (!empty($traits[1])) {
            foreach ($traits[1] as $index => $trait) {
                $traitName = $trait[0];
                $line = $this->getLineNumber($code, $trait[1]);
                $info = [
                    'name' => $traitName,
                    'line' => $line,
                    'type' => 'trait',
                    'methods' => []
                ];
                $this->extractMethods($code, $trait[1], $info);
                $this->classInfo[] = $info;
            }
        }
        // 处理函数
        if (!empty($functions[1])) {
            foreach ($functions[1] as $index => $function) {
                $functionName = $function[0];
                $line = $this->getLineNumber($code, $function[1]);
                $params = $functions[2][$index][0];
                $this->functionInfo[] = [
                    'name' => $functionName,
                    'line' => $line,
                    'params' => $params
                ];
            }
        }
    }
    /**
     * 提取类方法
     * 
     * @param string $code PHP代码
     * @param int $classOffset 类定义偏移量
     * @param array &$info 类信息引用
     */
    private function extractMethods($code, $classOffset, &$info) {
        // 查找类定义的位置
        $classPos = strpos($code, 'class', $classOffset);
        if ($classPos === false) {
            $classPos = strpos($code, 'interface', $classOffset);
        }
        if ($classPos === false) {
            $classPos = strpos($code, 'trait', $classOffset);
        }
        if ($classPos !== false) {
            // 查找类的开始花括号
            $bracePos = strpos($code, '{', $classPos);
            if ($bracePos !== false) {
                // 提取类内的方法
                $endPos = $this->findMatchingBrace($code, $bracePos);
                $classContent = substr($code, $bracePos, $endPos - $bracePos);
                preg_match_all('/function\s+(\w+)\s*\(([^)]*)\)/i', $classContent, $methods, PREG_OFFSET_CAPTURE);
                foreach ($methods[1] as $mIndex => $method) {
                    $methodName = $method[0];
                    $methodParams = $methods[2][$mIndex][0];
                    // 提取可见性
                    $methodVisibility = $this->getVisibility($classContent, $methods[0][$mIndex][1]);
                    $info['methods'][] = [
                        'name' => $methodName,
                        'params' => $methodParams,
                        'visibility' => $methodVisibility,
                        'static' => $this->isStatic($classContent, $methods[0][$mIndex][1])
                    ];
                }
            }
        }
    }
    /**
     * 提取类属性
     * 
     * @param string $code PHP代码
     * @param int $classOffset 类定义偏移量
     * @param array &$info 类信息引用
     */
    private function extractProperties($code, $classOffset, &$info) {
        $classPos = strpos($code, 'class', $classOffset);
        if ($classPos !== false) {
            $bracePos = strpos($code, '{', $classPos);
            if ($bracePos !== false) {
                $endPos = $this->findMatchingBrace($code, $bracePos);
                $classContent = substr($code, $bracePos, $endPos - $bracePos);
                preg_match_all('/(?:public|protected|private|var)\s+\$(\w+)/i', $classContent, $properties);
                foreach ($properties[1] as $property) {
                    $info['properties'][] = $property;
                }
            }
        }
    }
    /**
     * 获取方法可见性
     * 
     * @param string $content 类内容
     * @param int $offset 方法偏移量
     * @return string 可见性
     */
    private function getVisibility($content, $offset) {
        $beforeMethod = substr($content, 0, $offset);
        if (preg_match('/(public|protected|private)\s+function\s*$/', $beforeMethod)) {
            preg_match('/(public|protected|private)\s+function\s*$/', $beforeMethod, $matches);
            return $matches[1];
        }
        return 'public'; // 默认public
    }
    /**
     * 检查方法是否为static
     * 
     * @param string $content 类内容
     * @param int $offset 方法偏移量
     * @return bool 是否为static
     */
    private function isStatic($content, $offset) {
        $beforeMethod = substr($content, 0, $offset);
        return (bool)preg_match('/static\s+function\s*$/', $beforeMethod);
    }
    /**
     * 查找匹配的花括号
     * 
     * @param string $code PHP代码
     * @param int $bracePos 开始花括号位置
     * @return int 匹配花括号位置
     */
    private function findMatchingBrace($code, $bracePos) {
        $depth = 1;
        $pos = $bracePos;
        while ($depth > 0 && $pos < strlen($code)) {
            $pos++;
            if ($code[$pos] === '{') {
                $depth++;
            } elseif ($code[$pos] === '}') {
                $depth--;
            }
        }
        return $pos;
    }
    /**
     * 获取代码行号
     * 
     * @param string $code PHP代码
     * @param int $offset 偏移量
     * @return int 行号
     */
    private function getLineNumber($code, $offset) {
        $before = substr($code, 0, $offset);
        return substr_count($before, "\n") + 1;
    }
    /**
     * 构建Markdown文档
     */
    private function buildDocumentation() {
        $this->documentation = "# PHP 代码文档\n\n";
        $this->documentation .= "> 自动生成的代码文档\n\n";
        // 目录
        $this->documentation .= "## 目录\n\n";
        if (!empty($this->classInfo)) {
            $this->documentation .= "### 类 \n";
            foreach ($this->classInfo as $class) {
                $this->documentation .= "- [{$class['name']}](#" . strtolower($class['name']) . ")\n";
            }
        }
        if (!empty($this->functionInfo)) {
            $this->documentation .= "### 函数\n";
            foreach ($this->functionInfo as $function) {
                $this->documentation .= "- [{$function['name']}()](#" . strtolower($function['name']) . ")\n";
            }
        }
        $this->documentation .= "\n---\n\n";
        // 类文档
        if (!empty($this->classInfo)) {
            $this->documentation .= "## 类\n\n";
            foreach ($this->classInfo as $class) {
                $this->documentation .= "### {$class['name']}\n\n";
                if (isset($class['type'])) {
                    $this->documentation .= "**类型**: {$class['type']}\n\n";
                }
                $this->documentation .= "- **文件位置**: 第 {$class['line']} 行\n\n";
                if (isset($class['extends']) && $class['extends']) {
                    $this->documentation .= "- **继承自**: `{$class['extends']}`\n\n";
                }
                if (isset($class['implements']) && $class['implements']) {
                    $this->documentation .= "- **实现**: `{$class['implements']}`\n\n";
                }
                // 属性
                if (!empty($class['properties'])) {
                    $this->documentation .= "#### 属性\n\n";
                    foreach ($class['properties'] as $property) {
                        $this->documentation .= "- `\${$property}`\n";
                    }
                    $this->documentation .= "\n";
                }
                // 方法
                if (!empty($class['methods'])) {
                    $this->documentation .= "#### 方法\n\n";
                    foreach ($class['methods'] as $method) {
                        $visibility = isset($method['visibility']) ? $method['visibility'] : 'public';
                        $static = isset($method['static']) && $method['static'] ? 'static ' : '';
                        $this->documentation .= "##### `{$visibility} {$static}function {$method['name']}({$method['params']})`\n\n";
                    }
                    $this->documentation .= "\n";
                }
                $this->documentation .= "---\n\n";
            }
        }
        // 函数文档
        if (!empty($this->functionInfo)) {
            $this->documentation .= "## 函数\n\n";
            foreach ($this->functionInfo as $function) {
                $this->documentation .= "### {$function['name']}()\n\n";
                $this->documentation .= "- **文件位置**: 第 {$function['line']} 行\n";
                $this->documentation .= "- **参数**: `{$function['params']}`\n\n";
                $this->documentation .= "---\n\n";
            }
        }
    }
    /**
     * 添加自定义内容
     * 
     * @param string $content 要添加的内容
     */
    public function addContent($content) {
        $this->documentation .= $content . "\n\n";
    }
    /**
     * 保存文档到文件
     * 
     * @param string $filename 文件名
     * @return bool 是否成功
     */
    public function saveToFile($filename) {
        return file_put_contents($filename, $this->documentation) !== false;
    }
    /**
     * 获取最终文档
     * 
     * @return string Markdown内容
     */
    public function getDocumentation() {
        return $this->documentation;
    }
}

高级Markdown生成器(带样式和模板)

<?php
/**
 * AdvancedMarkdownGenerator - 高级Markdown文档生成器
 * 
 * 支持自定义模板、代码高亮、表格生成等功能
 */
class AdvancedMarkdownGenerator {
    private $template;
    private $content = [];
    private $toc = [];
    public function __construct() {
        $this->setDefaultTemplate();
    }
    /**
     * 设置模板
     * 
     * @param string $template 模板内容
     */
    public function setTemplate($template) {
        $this->template = $template;
    }
    /**
     * 设置默认模板
     */
    private function setDefaultTemplate() {
        $this->template = "# {{TITLE}}\n\n"
            . "> {{DESCRIPTION}}\n\n"
            . "## 目录\n\n"
            . "{{TOC}}\n\n"
            . "---\n\n"
            . "{{CONTENT}}";
    }
    /**
     * 生成文档
     * 
     * @param array $data 文档数据
     * @return string 生成的Markdown
     */
    public function generate($data) {
        $title = isset($data['title']) ? $data['title'] : '文档';
        $description = isset($data['description']) ? $data['description'] : '自动生成的文档';
        // 替换模板变量
        $output = str_replace('{{TITLE}}', $title, $this->template);
        $output = str_replace('{{DESCRIPTION}}', $description, $output);
        // 生成目录
        $tocContent = $this->generateTOC($data['sections']);
        $output = str_replace('{{TOC}}', $tocContent, $output);
        // 生成内容
        $content = $this->generateContent($data['sections']);
        $output = str_replace('{{CONTENT}}', $content, $output);
        return $output;
    }
    /**
     * 生成目录
     * 
     * @param array $sections 文档段落
     * @return string 目录Markdown
     */
    private function generateTOC($sections) {
        $toc = "";
        foreach ($sections as $section) {
            $toc .= "- [" . $section['title'] . "](#" . $this->slugify($section['title']) . ")\n";
        }
        return $toc;
    }
    /**
     * 生成内容
     * 
     * @param array $sections 文档段落
     * @return string 内容Markdown
     */
    private function generateContent($sections) {
        $content = "";
        foreach ($sections as $section) {
            $content .= "## " . $section['title'] . "\n\n";
            $content .= $section['content'] . "\n\n";
        }
        return $content;
    }
    /**
     * 生成表格
     * 
     * @param array $headers 表头
     * @param array $rows 数据行
     * @return string 表格Markdown
     */
    public function generateTable($headers, $rows) {
        $table = "| " . implode(" | ", $headers) . " |\n";
        $table .= "|" . str_repeat("---|", count($headers)) . "\n";
        foreach ($rows as $row) {
            $table .= "| " . implode(" | ", array_map('strval', $row)) . " |\n";
        }
        return $table;
    }
    /**
     * 生成代码块
     * 
     * @param string $code 代码内容
     * @param string $language 语言类型
     * @return string 代码块Markdown
     */
    public function generateCodeBlock($code, $language = 'php') {
        return "```{$language}\n{$code}\n```";
    }
    /**
     * 生成链接
     * 
     * @param string $text 显示文本
     * @param string $url URL地址
     * @return string 链接Markdown
     */
    public function generateLink($text, $url) {
        return "[{$text}]({$url})";
    }
    /**
     * 生成图片
     * 
     * @param string $src 图片路径
     * @param string $alt 替代文本
     * @return string 图片Markdown
     */
    public function generateImage($src, $alt = '') {
        return "![{$alt}]({$src})";
    }
    /**
     * 生成分隔线
     * 
     * @return string 分隔线Markdown
     */
    public function generateDivider() {
        return "---";
    }
    /**
     * 生成引用块
     * 
     * @param string $text 引用文本
     * @return string 引用Markdown
     */
    public function generateBlockquote($text) {
        return "> " . $text;
    }
    /**
     * 生成列表
     * 
     * @param array $items 列表项
     * @param bool $ordered 是否有序
     * @return string 列表Markdown
     */
    public function generateList($items, $ordered = false) {
        $list = "";
        if ($ordered) {
            foreach ($items as $index => $item) {
                $list .= ($index + 1) . ". {$item}\n";
            }
        } else {
            foreach ($items as $item) {
                $list .= "- {$item}\n";
            }
        }
        return $list;
    }
    /**
     * 生成任务列表
     * 
     * @param array $tasks 任务列表
     * @return string 任务列表Markdown
     */
    public function generateTaskList($tasks) {
        $list = "";
        foreach ($tasks as $task => $done) {
            $checkbox = $done ? '[x]' : '[ ]';
            $list .= "- {$checkbox} {$task}\n";
        }
        return $list;
    }
    /**
     * 生成嵌套列表
     * 
     * @param array $items 项目列表(支持嵌套)
     * @return string 嵌套列表Markdown
     */
    public function generateNestedList($items, $level = 0) {
        $list = "";
        $indent = str_repeat("  ", $level);
        foreach ($items as $item) {
            if (is_array($item)) {
                $list .= $indent . "- " . $item['title'] . "\n";
                if (isset($item['children'])) {
                    $list .= $this->generateNestedList($item['children'], $level + 1);
                }
            } else {
                $list .= $indent . "- " . $item . "\n";
            }
        }
        return $list;
    }
    /**
     * 生成锚点链接
     * 
     * @param string $text 显示文本
     * @param string $anchor 锚点名称
     * @return string 锚点Markdown
     */
    public function generateAnchorLink($text, $anchor) {
        return "[{$text}](#{$this->slugify($anchor)})";
    }
    /**
     * 生成脚注
     * 
     * @param string $text 脚注文本
     * @param int $number 脚注编号
     * @return string 脚注Markdown
     */
    public function generateFootnote($text, $number = null) {
        if ($number === null) {
            $number = count($this->footnotes) + 1;
        }
        $this->footnotes[$number] = $text;
        return "[^{$number}]";
    }
    /**
     * 获取所有脚注
     * 
     * @return string 脚注段落
     */
    public function getFootnotes() {
        $output = "\n---\n\n## 脚注\n\n";
        foreach ($this->footnotes as $number => $text) {
            $output .= "[^{$number}]: {$text}\n";
        }
        return $output;
    }
    /**
     * 转换字符串为slug
     * 
     * @param string $text 原始字符串
     * @return string slug字符串
     */
    private function slugify($text) {
        $text = strtolower(trim($text));
        $text = preg_replace('/[^a-z0-9\s-]/', '', $text);
        $text = preg_replace('/[\s-]+/', '-', $text);
        return $text;
    }
    private $footnotes = [];
}

使用示例

<?php
// 使用示例
require_once 'MarkdownDocumenter.php';
require_once 'AdvancedMarkdownGenerator.php';
// 示例1: 基础文档生成
$docGenerator = new MarkdownDocumenter();
// 从文件生成
$markdown = $docGenerator->generateFromFile('example.php');
$docGenerator->saveToFile('output_documentation.md');
// 或者从源代码生成
$sourceCode = <<<'CODE'
<?php
/**
 * 用户类
 */
class User {
    private $name;
    public function __construct($name) {
        $this->name = $name;
    }
    public function getName() {
        return $this->name;
    }
}
/**
 * 示例函数
 */
function hello($name) {
    return "Hello, " . $name;
}
CODE;
$markdown = $docGenerator->generateFromSource($sourceCode);
echo $markdown;
// 示例2: 高级文档生成
$advanced = new AdvancedMarkdownGenerator();
$data = [ => 'API 文档',
    'description' => '这是API的完整文档说明',
    'sections' => [
        [
            'title' => '概览',
            'content' => '这是一个示例API文档...'
        ],
        [
            'title' => '安装',
            'content' => $advanced->generateCodeBlock('composer install', 'bash')
        ],
        [
            'title' => '使用方法',
            'content' => '示例代码:'
                . $advanced->generateCodeBlock('<?php\n$api = new API();\n$result = $api->call();')
        ]
    ]
];
$markdown = $advanced->generate($data);
echo $markdown;
// 示例3: 生成高质量文档
$doc = new AdvancedMarkdownGenerator();
$sections = [
    [
        'title' => '项目介绍',
        'content' => implode("\n", [
            '这是一个强大的PHP项目,提供以下功能:',
            '',
            '```php',
            '// 快速开始',
            '$instance = new ClassName();',
            '$instance->method();',
            '```',
        ])
    ],
    [
        'title' => '配置说明',
        'content' => $doc->generateTable(
            ['配置项', '类型', '默认值', '说明'],
            [
                ['debug', 'bool', 'false', '是否开启调试模式'],
                ['cache', 'bool', 'true', '是否启用缓存'],
                ['timeout', 'int', '30', '超时时间(秒)'],
            ]
        )
    ],
    [
        'title' => 'API 参考',
        'content' => implode("\n", [
            '### getUser()',
            '',
            '获取用户信息',
            '',
            '| 参数 | 类型 | 说明 |',
            '|------|------|------|',
            '| id | int | 用户ID |',
            '',
            '**返回值**: array',
            '',
            '```php',
            '$info = $api->getUser(123);',
            '```',
        ])
    ]
];
$data = [ => '项目文档',
    'description' => '自动化生成的完整文档',
    'sections' => $sections
];
$markdown = $doc->generate($data);
file_put_contents('project_documentation.md', $markdown);

命令行工具版本

<?php
/**
 * markdown-doc.php - 命令行工具
 * 
 * 使用方法:
 * php markdown-doc.php <source_file.php> [output_file.md]
 */
require_once 'MarkdownDocumenter.php';
// 检查参数
if ($argc < 2) {
    echo "用法: php markdown-doc.php <source_file.php> [output_file.md]\n";
    exit(1);
}
$sourceFile = $argv[1];
$outputFile = isset($argv[2]) ? $argv[2] : 'documentation.md';
// 检查文件是否存在
if (!file_exists($sourceFile)) {
    echo "错误: 文件 '{$sourceFile}' 不存在\n";
    exit(1);
}
// 生成文档
$generator = new MarkdownDocumenter();
$markdown = $generator->generateFromFile($sourceFile);
// 保存文档
if ($generator->saveToFile($outputFile)) {
    echo "文档已生成: {$outputFile}\n";
    echo "文档大小: " . strlen($markdown) . " bytes\n";
} else {
    echo "错误: 无法保存文档\n";
    exit(1);
}

高级样式增强

<?php
/**
 * StyledMarkdownGenerator - 带样式的Markdown生成器
 */
class StyledMarkdownGenerator extends AdvancedMarkdownGenerator {
    /**
     * 生成美观的警告框
     * 
     * @param string $type 类型(info, warning, danger, success)
     * @param string $message 消息内容
     * @return string 警告框Markdown
     */
    public function generateAlert($type, $message) {
        $icons = [
            'info' => 'ℹ️',
            'warning' => '⚠️',
            'danger' => '🚨',
            'success' => '✅'
        ];
        $icon = isset($icons[$type]) ? $icons[$type] : $icons['info'];
        return "> {$icon} **" . strtoupper($type) . "**: {$message}";
    }
    /**
     * 生成代码对比
     * 
     * @param string $before 修改前
     * @param string $after 修改后
     * @return string 对比Markdown
     */
    public function generateDiff($before, $after) {
        return implode("\n", [
            "#### 修改前",
            "```php",
            $before,
            "```",
            "",
            "#### 修改后",
            "```php",
            $after,
            "```"
        ]);
    }
    /**
     * 生成扩展的表格(带对齐)
     * 
     * @param array $headers 表头
     * @param array $rows 数据
     * @param array $alignments 对齐方式
     * @return string 对齐表格
     */
    public function generateAlignedTable($headers, $rows, $alignments = []) {
        $table = "| " . implode(" | ", $headers) . " |\n";
        // 对齐标志
        $alignmentsSymbols = [
            'left' => ':---',
            'center' => ':---:',
            'right' => '---:'
        ];
        $alignRow = "|";
        foreach ($headers as $key => $header) {
            $align = isset($alignments[$key]) ? $alignments[$key] : 'left';
            $symbol = isset($alignmentsSymbols[$align]) ? $alignmentsSymbols[$align] : ':---';
            $alignRow .= " {$symbol} |";
        }
        $table .= $alignRow . "\n";
        foreach ($rows as $row) {
            $table .= "| " . implode(" | ", array_map('strval', $row)) . " |\n";
        }
        return $table;
    }
}

这个PHP Markdown文档生成工具提供了完整的解决方案,包括:

  1. 自动解析:从PHP源代码自动提取类、方法、属性、函数等信息
  2. 多种格式:支持类、接口、trait、函数等文档生成
  3. 高级功能:表格、代码块、链接、图片等Markdown元素
  4. 命令行工具:方便批量处理
  5. 灵活扩展:支持自定义模板和样式

使用这个工具可以快速生成专业的代码文档,提高开发效率。

抱歉,评论功能暂时关闭!