本文目录导读:

- 方法一:使用 PHPWord(最推荐,生成 .docx)
- 方法二:生成 PDF (防止篡改)
- 方法三:使用外部 API (如果不想在服务器装 Office)
- 方法四:生成 HTML 并导出(最快速,适合预览)
- 最佳实践与注意事项
在PHP中生成合同模板,核心需求是用数据填充预设的格式,并输出为可交互(可编辑)或不可交互(仅阅读)的文档,最主流的解决方案是使用 PHPWord,因为它功能全面,且能完美兼容 Office 文档。
以下是基于 PHPWord 的完整解决方案,涵盖从基础到进阶的多种方法。
使用 PHPWord(最推荐,生成 .docx)
这是最灵活、功能最强的方案,支持表格、图片、页眉页脚,并且生成的文档可以在 Word 中再次编辑。
安装 PHPWord
使用 Composer 安装(需要服务器有 Composer 环境):
composer require phpoffice/phpword
核心逻辑:使用 setValue 替换占位符
这是最常用的方法,在模板中写入 ${占位符},然后在 PHP 中替换。
模板准备(template.docx):
在 Word 中编辑合同,在需要动态变化的地方填写占位符,
甲方(盖章):
${party_a}合同金额:`${amount}元整。 签订日期:**${sign_date}`**
PHP 代码(生成合同):
<?php
require_once 'vendor/autoload.php';
use PhpOffice\PhpWord\TemplateProcessor;
// 1. 加载模板(模板文件必须存在)
$templateProcessor = new TemplateProcessor('template.docx');
// 2. 替换占位符(这里可以是数据库查询出来的值)
$templateProcessor->setValue('party_a', '北京某某科技有限公司');
$templateProcessor->setValue('amount', '壹佰贰拾万');
$templateProcessor->setValue('sign_date', date('Y年m月d日'));
// 3. 克隆并替换表格行(处理合同明细,如多条产品清单)
// 假设模板中有一行表格:| 产品名称 | 数量 | 单价 |
// 给这一行的单元格写入占位符:${product_name} | ${quantity} | ${price}
$products = [
['product_name' => '软件授权', 'quantity' => 10, 'price' => '1000元'],
['product_name' => '实施服务', 'quantity' => 2, 'price' => '5000元'],
];
// 克隆行数为2(插入两行数据),并替换其中的占位符
$templateProcessor->cloneRow('product_name', count($products));
foreach ($products as $index => $product) {
// 注意:cloneRow 后,占位符变为 ${product_name#$index},索引从1开始
$templateProcessor->setValue("product_name#".($index+1), $product['product_name']);
$templateProcessor->setValue("quantity#".($index+1), $product['quantity']);
$templateProcessor->setValue("price#".($index+1), $product['price']);
}
// 4. 保存生成的新文档
$templateProcessor->saveAs('output_contract_' . time() . '.docx');
echo "合同生成成功!";
?>
优点:
- 保留原始模板的所有格式(字体、页边距、水印)。
- 支持克隆行(单据明细)。
- 生成的是真正的 .docx 文件,易于存档。
生成 PDF (防止篡改)
如果合同用于法务审批或发送给客户签名且不希望对方修改内容,通常需要转为 PDF。
结合 PHPWord + DomPDF(或 MPDF):
<?php
require_once 'vendor/autoload.php';
use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\Settings;
// 1. 使用之前的方法生成 Word 内容(直接创建对象,不保存文件)
$phpWord = new \PhpOffice\PhpWord\PhpWord();
$section = $phpWord->addSection();
// 添加段落和文本(可以添加 HTML 文本)
$section->addText('合同编号:CON-2023-001', ['bold' => true], ['alignment' => 'center']);
$section->addText('甲方:某某公司');
$section->addText('乙方:个人');
// ... 这里可以使用文档编辑器的 API 构建复杂排版
// 2. 设置 PDF 渲染器(需要安装 dompdf)
Settings::setPdfRendererName(Settings::PDF_RENDERER_DOMPDF);
Settings::setPdfRendererPath(dirname(__DIR__) . '/vendor/dompdf/dompdf');
// 3. 保存为 PDF
$objWriter = IOFactory::createWriter($phpWord, 'PDF');
$objWriter->save('output_contract.pdf');
?>
注意:该方案需要额外安装 dompdf: composer require dompdf/dompdf。
使用外部 API (如果不想在服务器装 Office)
如果业务量极大,且需要复杂的在线编辑(多人协作),可以选择:
- 阿里云 Word 转 PDF
- 腾讯云 文档处理
- 反代 Google Docs / OnlyOffice
核心思路:将原生表格或 JSON 数据发送至 API,返回生成好的 URL 或文件流。
生成 HTML 并导出(最快速,适合预览)
如果你只是需要网页预览或者打印,直接用 HTML + CSS 即可。
<?php
// contract_template.php
$data = [ => '采购合同',
'party_a' => '买家',
'items' => [
['name' => '苹果', 'qty' => '10箱', 'price' => '5000'],
['name' => '梨', 'qty' => '5箱', 'price' => '2000'],
]
];
?>
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title><?php echo $data['title']; ?></title></head>
<body>
<style>
/* 专门为打印设计的 CSS */
@media print { body { font-family: SimSun; } }
table { border-collapse: collapse; width: 100%; }
td, th { border: 1px solid #000; padding: 8px; }
</style>
<h2>合同编号:<?php echo $data['party_a']; ?></h2>
<table>
<tr><th>产品</th><th>数量</th><th>价格</th></tr>
<?php foreach ($data['items'] as $item): ?>
<tr>
<td><?php echo $item['name']; ?></td>
<td><?php echo $item['qty']; ?></td>
<td><?php echo $item['price']; ?></td>
</tr>
<?php endforeach; ?>
</table>
<script>window.print();</script>
</body>
</html>
优点:零依赖,服务器无需 Office。 缺点:需要用户手动“另存为 PDF”或打印。
最佳实践与注意事项
- 防止 SQL 注入:从数据库读取数据替换时,使用 PDO 预处理。
- 路径安全:生成的合同文件放在
uploads或contracts目录下,文件名建议加上time()或uniqid()避免冲突。 - 编码问题:如果使用 PHPWord 模板,请确保模板
.docx文件中的占位符必须是大写字母(如{NAME}),且不要有空格,否则替换失败。 - 图片处理:如果合同需要印章(公章),PHPWord 提供
addImage()方法,但最好用透明底的 PNG 覆盖在最后位置。
- 常规业务:推荐 方法一 (PHPWord + docx),用户拿到后可再改。
- 法律效力:推荐 方法二 (PHPWord + PDF),防篡改。
- 快速原型:推荐 方法四 (HTML + CSS)。
如果需要我提供一个完整的 TemplateProcessor 处理嵌套表格或复杂条件判断的具体代码,可以告诉我你的具体合同结构。