用phpword生成.docx最稳,它封装openxml规范、纯php实现、部署简单;需注意样式传数组而非字符串、设正确header、及时unset释放内存、图片用绝对路径或data uri。

用 PHPWord 生成 .docx 最稳,别手写 XML
直接拼接 Word 的 XML 结构看似轻量,实际极易出错:一个命名空间漏了、w:document 深度不对、甚至时间戳格式不合法,都会导致文件打不开或提示“文件已损坏”。PHPWord 封装了 OpenXML 规范,把段落、表格、样式这些操作转成直观方法调用,省去底层细节。它不依赖 COM 或 LibreOffice,纯 PHP 实现,部署简单。
实操建议:
- 用 Composer 安装:
composer require phpoffice/phpword(注意不是phpword单包名) - 导出前必须设好 Content-Type 和 Header:
header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');和header('Content-Disposition: attachment;filename="report.docx"'); - 避免在生成过程中 echo 或 var_dump —— 任何额外输出都会污染二进制流,导致文档损坏
addText() 和 addTable() 的样式参数容易传错类型
很多人以为样式是字符串,比如写 $section->addText('标题', 'bold'),结果没加粗。其实 addText() 第二个参数是数组,键名必须严格匹配文档定义:'bold' => true、'size' => 24、'color' => 'FF0000'。表格单元格样式同理,addCell() 不接受字符串类名,得传 ['bgColor' => 'EEEEEE'] 这样的数组。
常见错误现象:
立即学习“PHP免费学习笔记(深入)”;
- 文字全变成默认宋体小五号 —— 样式数组为空或键名拼错(如写成
'Bold'或'font-bold') - 表格边框消失 —— 忘了给
addTable()传样式数组,或漏掉'borderSize' => 12这类关键项 - 中文乱码 —— 没在
addText()的第三个参数(字体名)里指定'SimSun'或'Microsoft YaHei'
大数据量导出时内存爆掉,save() 前记得 unset() 文档对象
PHPWord 把整个文档结构存在内存里,生成千行表格+图片后,对象可能占上百 MB。如果导出完不释放,PHP 进程持续持有引用,下次请求就更容易超限。这不是 bug,是设计使然 —— 它没做流式写入。
性能影响明显:
- 导出 5000 行数据时,内存峰值常超 256MB(尤其开了 Xdebug)
- Apache 下可能触发
Fatal error: Allowed memory size exhausted - 解决办法不是调大
memory_limit,而是主动清理:unset($phpWord); unset($section);在$objWriter->save('php://output')之后立刻执行
图片插入路径错位、显示为红叉,addImage() 只认绝对路径或 data:// URI
addImage() 不支持相对路径(如 ./images/logo.png),也不走 PHP 的 include_path。它要么要服务器上的绝对磁盘路径(/var/www/html/images/logo.png),要么用 base64 编码的 data:image/png;base64,...。用 __DIR__ . '/images/logo.png' 是安全写法;用 $_SERVER['DOCUMENT_ROOT'] 则要注意符号链接和权限。
容易踩的坑:
- 本地开发用
http://localhost/images/logo.png——addImage()不支持 HTTP URL - 图片权限为 600,PHP 进程读不到,静默失败(不报错,但 Word 里显示红叉)
- 图片太大(如 5MB PNG)导致生成慢、内存飙升,建议提前压缩或转 WebP 后再嵌入
复杂点在于:Word 对嵌入图片的 DPI、尺寸缩放、环绕方式都敏感,但 PHPWord 的 addImage() 参数有限,想精确控制就得手动改 XML —— 那就又回到开头说的,别手写 XML。











