ThinkPHP 8.0 默认不渲染 Markdown,因视图系统仅按后缀加载文件而不解析语法;需在控制器中用 Markdown 解析器转换后传入模板,并用 {$var|raw} 输出。

ThinkPHP 8.0 默认不支持 Markdown 渲染,fetch() 和 view() 直接输出的是原始 HTML 字符串,不会自动解析 .md 文件或转换 Markdown 语法。必须手动集成解析器并控制输出流程。
为什么 fetch('article/index') 不会渲染 Markdown
ThinkPHP 8 的视图系统默认只识别配置中定义的模板后缀(如 .html、.php),且调用的是 PHP 原生模板驱动或 think-view 的编译型引擎。它把 .md 当作普通文本文件读取,不做语法解析,也不会执行 Markdown::convert() 类操作。
- 模板路径匹配逻辑在
think\View中由parseTemplate()控制,只按后缀和目录规则定位,不触发内容转换 - 即使你把模板命名为
index.md并修改配置'view_suffix' => 'md',也只是让框架去加载该文件,内容仍原样输出 -
assign()传入的变量如果是 Markdown 字符串,也只会被当作普通字符串插入,不会自动转义或渲染
如何在视图中安全渲染 Markdown 内容
推荐在控制器中完成解析,再将 HTML 字符串传给模板;避免在模板里调用 eval 或引入第三方函数,防止 XSS 和性能损耗。
将 Markdown 格式的回复转换为适合 Telegram 的富文本,避免渲染错误。适用于用户偏好 Markdown 但目标平台为 Telegram 的场景。
- 安装解析器:
composer require michelf/php-markdown(轻量、无依赖)或composer require league/commonmark(更现代、扩展性强) - 在控制器中解析并赋值:
$content = file_get_contents(app()->getAppPath() . 'view/article/content.md'); $html = \Michelf\Markdown::defaultTransform($content); $this->assign('rendered', $html); - 模板中直接输出(注意已转义):
{$rendered|raw}—— 必须加|raw,否则会被二次 HTML 转义 - 若内容来自数据库或用户输入,务必先过滤危险标签(如
<script>),再交给 Markdown 解析器,顺序不能反
view() 辅助函数 + 自定义模板驱动的边界
有人尝试写一个 MarkdownDriver 实现 TemplateHandlerInterface,让 view('article/read') 自动识别 .md 并渲染。这可行但不推荐:
立即学习“PHP免费学习笔记(深入)”;
- TP8 的
think-view驱动设计面向编译型模板(如缓存 AST),而 Markdown 是纯文本流式解析,无法有效缓存中间态 - 每次请求都重新解析 Markdown 文件,比 PHP 模板慢 3–5 倍,尤其含大量表格或代码块时
- 错误处理困难:某行语法错误会导致整个页面白屏,且 TP8 默认异常页是 PHP 模板,无法捕获 Markdown 解析异常
- 调试成本高:无法像
.html模板那样在浏览器查看源码定位问题,日志里只显示「Parse error in markdown」这类模糊提示
真正要支持 Markdown 视图,核心就一条:别让它进模板引擎流水线。解析放在控制器或服务层,确保输入可控、输出可信、错误可捕获。最易忽略的是 |raw 的使用时机——漏了它,你看到的永远是一堆未转义的 <p><strong> 标签,而不是真实渲染效果。


















