Laravel-dompdf生成PDF能否添加书签?替代方案有哪些?
我有一个基于Laravel 8.75的应用,使用barryvdh/laravel-dompdf 2.0.1版本,功能是从数据库生成PDF并保存到存储中。我需要为PDF里的每一组动态数据添加书签,之前看到2012年的资料说这个包不支持该功能,但那信息已经过时了。我尝试在Blade视图里添加锚点,还启用了Dompdf配置中的PHP选项,但都没生效。
我的create方法代码如下:
public function create() { $baseUrl = config('app.url') . '/site/public/'; ini_set('memory_limit', '256M'); $datas = Compatibilite::all()->groupBy('marque'); foreach ($datas as $marque => $group) { $datas[$marque] = $group->sortBy('ordre'); }; try { $pdf = Pdf::loadView('pdf.compatibilityTablePdf', [ 'datas' => $datas, 'baseUrl' => $baseUrl, ]); } catch (\Throwable $th) { Log::error($th); return; } if($pdf) { try { $content = $pdf->download()->getOriginalContent(); } catch (\Throwable $th) { Log::error($th); return; } } else { Log::error('Erreur de création du pdf'); } if($content) { try { Storage::put('public/docs/doc.pdf', $content); } catch (\Throwable $th) { Log::error($th); return; } } }
对应的PDF Blade视图代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Compatibilites</title> </head> <body> <header> [...] </header> <footer> [...] </footer> <main> @foreach($datas as $brand => $elements) <div> <h2><a name="{{$brand}}"></a>{{$brand}}</h2> <table> <thead> [...] </thead> <tbody> [...] </tbody> </table> </div> @endforeach </main> </body> </html>
请问现在能否通过laravel-dompdf为生成的PDF添加书签?如果不行,有哪些替代包可以使用?
一、laravel-dompdf 2.0.1 是否支持书签?
目前barryvdh/laravel-dompdf 2.0.1底层依赖dompdf 2.x版本,dompdf本身不原生支持PDF书签(大纲)功能。你尝试的HTML锚点仅能创建文档内跳转链接,不会生成PDF的书签大纲。
若要强行实现,可通过操作dompdf底层对象手动添加大纲,但步骤繁琐且稳定性依赖版本:
- 生成PDF后获取dompdf底层实例
- 遍历分组数据,手动为每个品牌添加大纲条目并关联对应页码
- 重新渲染PDF
示例代码片段(需适配你的场景):
// 在生成$pdf对象后 $dompdf = $pdf->getDomPDF(); $canvas = $dompdf->get_canvas(); $outline = $canvas->get_cpdf()->newOutline(); foreach ($datas as $brand => $elements) { // 需要额外处理获取品牌标题对应的页码 $pageNumber = ...; $outline->add_entry($brand, $pageNumber); } // 重新输出PDF内容 $content = $dompdf->output();
这种方法需要深入了解dompdf底层API,不是官方推荐方案。
二、替代方案
如果追求便捷性和稳定性,推荐以下Laravel PDF生成包:
1. spatie/browsershot
基于Puppeteer/Headless Chrome生成PDF,支持通过<h1>/<h2>等标题标签自动生成书签,只需启用Chrome的大纲配置:
use Spatie\Browsershot\Browsershot; Browsershot::html(view('pdf.compatibilityTablePdf', ['datas' => $datas])->render()) ->setOption('displayHeaderFooter', true) ->setOption('headerTemplate', '<header>...</header>') ->setOption('footerTemplate', '<footer>...</footer>') ->setOption('printBackground', true) ->setOption('generateDocumentOutline', true) // 启用书签 ->save(storage_path('app/public/docs/doc.pdf'));
优点:HTML/CSS支持完整,书签生成简单,样式还原度高;缺点:需安装Node.js和Puppeteer。
2. niklasravnsborg/laravel-pdf
底层依赖TCPDF,原生支持书签功能,可手动添加或通过HTML标签转换:
use PDF; $pdf = PDF::loadView('pdf.compatibilityTablePdf', ['datas' => $datas]); $pdf->setTitle('Compatibilites'); // 手动添加书签 foreach ($datas as $brand => $elements) { $pdf->addBookmark($brand); } $pdf->save(storage_path('app/public/docs/doc.pdf'));
优点:纯PHP实现,无需额外依赖,书签功能成熟;缺点:HTML/CSS支持度略逊于其他方案。
3. barryvdh/laravel-snappy
底层依赖wkhtmltopdf,支持通过<h1>-<h6>标签自动生成书签,只需启用配置选项:
use SnappyPDF; SnappyPDF::loadView('pdf.compatibilityTablePdf', ['datas' => $datas]) ->setOption('outline', true) // 启用书签 ->setOption('outline-depth', 2) // 设置书签层级 ->save(storage_path('app/public/docs/doc.pdf'));
优点:HTML/CSS支持较好,书签生成简单;缺点:需安装wkhtmltopdf二进制文件。
内容的提问来源于stack exchange,提问作者Petitemo

