CakePhp 3.x、TCPDF、htmlspecialchars
CakePhp 3.x, TCPDF, htmlspecialchars
我已经按照文档安装了插件 "CakePDF":https://github.com/FriendsOfCake/CakePdf
现在我想构建第一个 PDF,但出现以下错误:
这是我在bootstrap.php中的配置:
Configure::write('CakePdf', [
'engine' => 'CakePdf.Tcpdf',
'margin' => [
'bottom' => 15,
'left' => 50,
'right' => 30,
'top' => 45
],
'download' => true,
'encoding' => 'UTF-8'
]);
我编写的唯一代码是模板中的以下代码:
$pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false);
这是 functions.php 中第 68 行的代码:
function h($text, $double = true, $charset = null)
{
if (is_string($text)) {
//optimize for strings
} elseif (is_array($text)) {
$texts = [];
foreach ($text as $k => $t) {
$texts[$k] = h($t, $double, $charset);
}
return $texts;
} elseif (is_object($text)) {
if (method_exists($text, '__toString')) {
$text = (string)$text;
} else {
$text = '(object)' . get_class($text);
}
} elseif (is_bool($text)) {
return $text;
}
static $defaultCharset = false;
if ($defaultCharset === false) {
$defaultCharset = mb_internal_encoding();
if ($defaultCharset === null) {
$defaultCharset = 'UTF-8';
}
}
if (is_string($double)) {
$charset = $double;
}
return htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE, ($charset) ? $charset : $defaultCharset, $double);
}
我非常困惑,找不到任何解决方案。有人有想法吗?
我想,我找到了罪魁祸首。 TCPDF 的构造方法将 mb_internal_encoding
设置为 ASCII
。 (tcpdf.php 第 1838 行)
我在评论中发现了一个提示:Please note that this method sets the mb_internal_encoding to ASCII, so if you are using the mbstring module functions with TCPDF you need to correctly set/unset the mb_internal_encoding when needed.
但现在我需要有关如何正确使用 tcpdf 和 mb_internal_encoding
的建议(没有 cake 或 tcpdf 的问题)。
抱歉提问,我绝对是初学者。 ;)
如您所想,问题 is/was TCPDF class 与 mb_internal_encoding()
混淆,后者在 CakePHPs h()
函数中用于确定应用程序默认值编码,以防没有明确的编码作为参数传递。
我不是 TCPDF 专家,很久没用过它了,但是快速浏览一下当前的源代码,我很难理解为什么它会乱用内部编码,因为库使用的唯一 mb_*
函数是 mb_convert_encoding()
,其中传递了两个编码参数,因此根本没有使用内部编码。话虽如此,我会将此作为 bug/issue 报告给 TCPDF 开发人员。
无论如何,您遇到这个问题只是因为您使用 CakePDF 的方式不对。无需手动创建 PDF 引擎实例,这就是 CakePDF 自动为您完成的,这几乎是插件的全部要点,它抽象了 PDF 创建,因此您只需要在中构建适当的 HTML你的视图模板。这样,您还可以避免当前遇到的 TCPDF 编码问题,因为在创建 PDF 引擎实例 之前 呈现视图模板。
tl;博士
长话短说,只在视图模板中构建 HTML,如果您确实需要访问 PDF 引擎实例,因为您需要做的事情只能通过这种方式实现,那么 CakePDF 不是您要找的插件。
在尝试查找和调试相同错误一个多小时后,我在使用 TCPDF 后将值重置为 UTF-8
- 一切正常之前:
$pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false);
///...create, save, display your pdf
// Reset the encoding forced from tcpdf
mb_internal_encoding('UTF-8');
我也试过在 new TCPDF
调用后直接重置它,一切都很好。我不知道这次重置会出什么问题 :) 我的 PDF 在此之后看起来仍然一样,但电子邮件会再次发送。
通过扩展 TCPDF class 放回初始编码,并使用新的 class:
class TCPDF_repaired extends TCPDF{
public function __construct($orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding='UTF-8', $diskcache=false, $pdfa=false) {
parent::__construct($orientation, $unit, $format, $unicode, $encoding, $diskcache, $pdfa);
mb_internal_encoding($this->internal_encoding);
}
};
我已经按照文档安装了插件 "CakePDF":https://github.com/FriendsOfCake/CakePdf
现在我想构建第一个 PDF,但出现以下错误:
这是我在bootstrap.php中的配置:
Configure::write('CakePdf', [
'engine' => 'CakePdf.Tcpdf',
'margin' => [
'bottom' => 15,
'left' => 50,
'right' => 30,
'top' => 45
],
'download' => true,
'encoding' => 'UTF-8'
]);
我编写的唯一代码是模板中的以下代码:
$pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false);
这是 functions.php 中第 68 行的代码:
function h($text, $double = true, $charset = null)
{
if (is_string($text)) {
//optimize for strings
} elseif (is_array($text)) {
$texts = [];
foreach ($text as $k => $t) {
$texts[$k] = h($t, $double, $charset);
}
return $texts;
} elseif (is_object($text)) {
if (method_exists($text, '__toString')) {
$text = (string)$text;
} else {
$text = '(object)' . get_class($text);
}
} elseif (is_bool($text)) {
return $text;
}
static $defaultCharset = false;
if ($defaultCharset === false) {
$defaultCharset = mb_internal_encoding();
if ($defaultCharset === null) {
$defaultCharset = 'UTF-8';
}
}
if (is_string($double)) {
$charset = $double;
}
return htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE, ($charset) ? $charset : $defaultCharset, $double);
}
我非常困惑,找不到任何解决方案。有人有想法吗?
我想,我找到了罪魁祸首。 TCPDF 的构造方法将 mb_internal_encoding
设置为 ASCII
。 (tcpdf.php 第 1838 行)
我在评论中发现了一个提示:Please note that this method sets the mb_internal_encoding to ASCII, so if you are using the mbstring module functions with TCPDF you need to correctly set/unset the mb_internal_encoding when needed.
但现在我需要有关如何正确使用 tcpdf 和 mb_internal_encoding
的建议(没有 cake 或 tcpdf 的问题)。
抱歉提问,我绝对是初学者。 ;)
如您所想,问题 is/was TCPDF class 与 mb_internal_encoding()
混淆,后者在 CakePHPs h()
函数中用于确定应用程序默认值编码,以防没有明确的编码作为参数传递。
我不是 TCPDF 专家,很久没用过它了,但是快速浏览一下当前的源代码,我很难理解为什么它会乱用内部编码,因为库使用的唯一 mb_*
函数是 mb_convert_encoding()
,其中传递了两个编码参数,因此根本没有使用内部编码。话虽如此,我会将此作为 bug/issue 报告给 TCPDF 开发人员。
无论如何,您遇到这个问题只是因为您使用 CakePDF 的方式不对。无需手动创建 PDF 引擎实例,这就是 CakePDF 自动为您完成的,这几乎是插件的全部要点,它抽象了 PDF 创建,因此您只需要在中构建适当的 HTML你的视图模板。这样,您还可以避免当前遇到的 TCPDF 编码问题,因为在创建 PDF 引擎实例 之前 呈现视图模板。
tl;博士
长话短说,只在视图模板中构建 HTML,如果您确实需要访问 PDF 引擎实例,因为您需要做的事情只能通过这种方式实现,那么 CakePDF 不是您要找的插件。
在尝试查找和调试相同错误一个多小时后,我在使用 TCPDF 后将值重置为 UTF-8
- 一切正常之前:
$pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false);
///...create, save, display your pdf
// Reset the encoding forced from tcpdf
mb_internal_encoding('UTF-8');
我也试过在 new TCPDF
调用后直接重置它,一切都很好。我不知道这次重置会出什么问题 :) 我的 PDF 在此之后看起来仍然一样,但电子邮件会再次发送。
通过扩展 TCPDF class 放回初始编码,并使用新的 class:
class TCPDF_repaired extends TCPDF{
public function __construct($orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding='UTF-8', $diskcache=false, $pdfa=false) {
parent::__construct($orientation, $unit, $format, $unicode, $encoding, $diskcache, $pdfa);
mb_internal_encoding($this->internal_encoding);
}
};