80 lines
3.0 KiB
PHP
80 lines
3.0 KiB
PHP
<?php
|
||
// app/service/pdf/PdfHelper.php
|
||
namespace app\common\utils\pdf\service;
|
||
|
||
class PdfHelper
|
||
{
|
||
/** 从文件加载 HTML(支持占位符 {{key}} 简单替换) */
|
||
public static function loadTemplate(string $file, array $vars = []): string
|
||
{
|
||
if (!is_file($file)) {
|
||
throw new \RuntimeException("Template not found: {$file}");
|
||
}
|
||
$html = file_get_contents($file);
|
||
if ($vars) {
|
||
$search = [];
|
||
$replace = [];
|
||
foreach ($vars as $k => $v) {
|
||
$search[] = '{{' . $k . '}}';
|
||
$replace[] = htmlspecialchars((string)$v, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
||
}
|
||
$html = str_replace($search, $replace, $html);
|
||
}
|
||
return $html;
|
||
}
|
||
|
||
/**
|
||
* 把 HTML 里的相对资源路径(img/link/script href/src)改成绝对路径
|
||
* 仅处理以 ./ ../ 或非 http(s) 的相对量;base 传 public/assets/pdf 等目录
|
||
*/
|
||
public static function absolutizeAssetUrls(string $html, string $baseDir): string
|
||
{
|
||
$baseDir = rtrim($baseDir, DIRECTORY_SEPARATOR);
|
||
// img src
|
||
$html = preg_replace_callback('#(<img[^>]+src=["\'])([^"\']+)(["\'])#i', function($m) use ($baseDir){
|
||
$u = $m[2];
|
||
if (preg_match('#^https?://#i', $u) || strpos($u, 'data:') === 0) return $m[0];
|
||
$abs = realpath($baseDir . DIRECTORY_SEPARATOR . ltrim($u, '/')) ?: ($baseDir . '/' . ltrim($u, '/'));
|
||
return $m[1] . $abs . $m[3];
|
||
}, $html);
|
||
|
||
// link href(如果你在 HTML 里写了 <link>,通常建议走 css_files 方式,这里也兼容)
|
||
$html = preg_replace_callback('#(<link[^>]+href=["\'])([^"\']+)(["\'])#i', function($m) use ($baseDir){
|
||
$u = $m[2];
|
||
if (preg_match('#^https?://#i', $u)) return $m[0];
|
||
$abs = realpath($baseDir . DIRECTORY_SEPARATOR . ltrim($u, '/')) ?: ($baseDir . '/' . ltrim($u, '/'));
|
||
return $m[1] . $abs . $m[3];
|
||
}, $html);
|
||
|
||
return $html;
|
||
}
|
||
|
||
|
||
/**
|
||
* 渲染一个原生 PHP 模板为字符串
|
||
* @param string $file 模板路径(如 resource/templates/stock-order.php)
|
||
* @param array $vars 将在模板中以变量名存在(如 $data)
|
||
* @return string 完整 HTML
|
||
*/
|
||
public static function render(string $file, array $vars = []): string
|
||
{
|
||
if (!is_file($file)) {
|
||
throw new \RuntimeException("Template not found: {$file}");
|
||
}
|
||
// 将键名导出为同名变量,例如 'data' => [...] 变为 $data
|
||
extract($vars, EXTR_OVERWRITE);
|
||
|
||
// 开启缓冲,将 include 的输出抓取为字符串
|
||
ob_start();
|
||
ob_implicit_flush(false);
|
||
try {
|
||
/** @noinspection PhpIncludeInspection */
|
||
include $file;
|
||
} catch (\Throwable $e) {
|
||
// 清理缓冲并抛出更清晰的异常
|
||
ob_end_clean();
|
||
throw $e;
|
||
}
|
||
return ob_get_clean();
|
||
}
|
||
} |