saggre/phpdocumentor-markdown
phpDocumentor Markdown template that generates GitHub/GitLab-ready docs from PHP source. Documents classes, interfaces, traits, functions, methods, properties, types, modifiers, and inheritance. Run phpdoc with the template to output Markdown for repos, wikis, or AI context.
Installation:
composer require --dev saggre/phpdocumentor-markdown
Ensure phpDocumentor is installed globally or via Composer (composer require --dev phpdoc/phpdocumentor).
First Run:
phpdoc --directory=src --target=docs --template="vendor/saggre/phpdocumentor-markdown/themes/markdown"
This generates Markdown docs in the docs/ directory.
Composer Script (Optional):
Add to composer.json for one-command generation:
"scripts": {
"docs:generate": "phpdoc --directory=src --target=docs --template=\"vendor/saggre/phpdocumentor-markdown/themes/markdown\""
}
Run with:
composer docs:generate
Verify Output:
Check docs/ for generated .md files (e.g., Home.md, classes/YourClass.md).
@param, @return, @throws).composer docs:generate to update docs/ from src/.docs/ to the repo (or symlink to a wiki/ folder for GitLab).phpdoc --directory=src --target=docs --template="vendor/saggre/phpdocumentor-markdown/themes/markdown" --cache=none
--cache=none forces regeneration (useful for CI)..github/workflows/docs.yml):
name: Generate Docs
on: [push]
jobs:
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: composer install
- run: composer docs:generate
- uses: actions/upload-artifact@v3
with:
name: docs
path: docs/
docs/ as an artifact or push to a gh-pages branch.docs/ to the wiki.vendor/saggre/phpdocumentor-markdown/themes/markdown/ to templates/markdown/ and modify Twig files (e.g., header.md.twig, class.md.twig).
Update the template path in composer.json:
"scripts": {
"docs:generate": "phpdoc --directory=src --target=docs --template=\"templates/markdown\""
}
phpdoc.dist.xml to filter sources:
<phpdocumentor>
<files>
<directory name="src" exclude="Tests/,Models/User.php"/>
</files>
</phpdocumentor>
Documenting Artisan Commands:
Add PHPDoc to command classes (e.g., app/Console/Commands/YourCommand.php):
/**
* @param string $argument Description of argument.
* @throws \Exception If validation fails.
*/
protected function handle($argument): void
The template will generate a dedicated .md file for the command.
Service Container Bindings:
Document interfaces/contracts (e.g., app/Contracts/YourContract.php) to auto-generate API-like docs.
Event Listeners:
Use @see tags to link events to listeners:
/**
* @see \Illuminate\Auth\Events\Registered
*/
public function handle(Registered $event)
{% extends %} to create reusable layouts (e.g., base.md.twig for shared headers/footers).templates/markdown/macros.twig:
{# templates/markdown/macros.twig #}
{% macro laravel_note(content) %}
> **Laravel Note**: {{ content }}
{% endmacro %}
Use in templates:
{{ _self.laravel_note('Use Facades for external services.') }}
GitHub Wiki Limitations:
.md files (e.g., classes/YourClass.md) break in GitHub wikis.YourClass.md in root).PHPDoc Parsing Quirks:
@param types or missing @return may cause malformed tables.// Good
/**
* @param string $name [Description]
* @return int
*/
// Bad (avoid)
/**
* @param $name
*/
Template Caching:
phpdoc caches templates; changes may not reflect until cache is cleared.--cache=none or delete phpdoc.cache/ manually.Twig Escaping:
|, _) in docblocks may break Markdown.{{ docblock|replace({'|': '\|', '_': '\_'}) }}
Verify PHPDoc Parsing:
Run with --parse-only to check if PHPDoc reads your annotations:
phpdoc --directory=src --parse-only
Look for warnings in output.
Inspect Generated Markdown:
phpdoc --template="vendor/saggre/phpdocumentor-markdown/themes/markdown" --debug to see Twig rendering steps.Template Debugging:
templates/markdown/config.twig:
{# config.twig #}
{% set debug = true %}
docs/_debug/ for rendered Twig variables.File Extensions in URLs:
.md from links (e.g., [Class](classes/YourClass)).use_file_extensions in phpdoc.dist.xml:
<phpdocumentor>
<template name="templates/markdown" use_file_extensions="true"/>
</phpdocumentor>
Table of Contents:
toc.md.twig:
{% for method in element.methods %}
{% if method.access !== 'private' %}
- [{{ method.name }}](#{{ method.name }})
{% endif %}
{% endfor %}
Custom Directories:
docs/ but you want api-docs/.--target:
phpdoc --directory=src --target=api-docs --template="..."
Add Custom Sections:
class.md.twig to include Laravel-specific sections (e.g., migrations, policies):
{# templates/markdown/class.md.twig #}
## Policies
{% if element.policies|length > 0 %}
{% for policy in element.policies %}
- [{{ policy }}]({{ policy }}.md)
{% endfor %}
{% endif %}
Post-Processing:
find docs -name "*.md" -exec sed -i '/^# /a \n'
How can I help you explore Laravel packages today?