CakePhp 3.x、TCPDF、htmlspecialchars

CakePhp 3.x、TCPDF、htmlspecialchars,php,cakephp,cakephp-3.0,tcpdf,Php,Cakephp,Cakephp 3.0,Tcpdf,我已经按照以下文档安装了插件“CakePDF”: 现在,我想构建第一个PDF,但出现以下错误: 这是我在bootstrap.php中的配置: Configure::write('CakePdf', [ 'engine' => 'CakePdf.Tcpdf', 'margin' => [ 'bottom' => 15, 'left' => 50, 'right' => 30, 'top'

我已经按照以下文档安装了插件“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\u内部编码设置为
ASCII
。(tcpdf.php第1838行)

我在评论中发现了一个提示:
请注意,此方法将mb\u内部\u编码设置为ASCII,因此如果您将mbstring模块函数与TCPDF一起使用,则需要在需要时正确设置/取消设置mb\u内部\u编码。

但是现在我需要一个如何正确使用tcpdf和
mb_internal_编码
的建议(没有cake或tcpdf的问题)


对不起,我是个十足的初学者

如您所想,问题在于/是TCPDF类与
mb_internal_encoding()
相混淆,该类在CakePHPs
h()
函数中用于确定应用程序的默认编码,以防没有显式编码作为参数传递

我不是TCPDF专家,很久没有使用过它了,但从当前的源代码来看,我很难理解为什么它会摆弄内部编码,因为库使用的唯一函数是
mb\u convert\u encoding()
,其中传递了两个编码参数,所以根本没有使用内部编码。也就是说,我会将此作为一个错误/问题报告给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');

我还尝试在调用
newtcpdf
后直接重置它,一切都很好。我不知道重置后会出现什么问题:)我的PDF在重置后看起来仍然一样,但电子邮件会再次发送。

通过扩展TCPDF类,将取消初始编码放回原处,并使用新类:

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);
    }
};

根据错误消息,您正在为应用程序使用
ASCII
编码(
app.encoding
)。是这样吗?如果是这样,你为什么要这么做?如果不是这样,请检查在应用程序引导中是否正确调用了
mb_internal_encoding()
,以及它是否可能在应用程序中的其他点被覆盖。是的,显然我使用的是ASCII。但是为什么呢?我已经在我的帖子中添加了function.php的代码。请注意,为什么要在视图模板中手动创建TCPDF实例?CakePDF是自动完成的。你有CakePHP3下的tcpdf文档吗?或者我可以从中找到一些说明的建议?没有特别的TCPDF文档,除了配置选项之外,它对每个引擎都适用。正在呈现视图模板内容,然后将其传递到配置的PDF引擎。我将报告此情况,感谢您的建议。这像看起来那么容易吗?我只需要在模板中创建我想要的HTML,CakePDF为我创建其余的?这很奇怪。顺便说一句:在tcpdf.php中删除构造函数和解构器方法中的if条件可以解决
ASCII
@Leyla的问题是的,这正是CakePDF的工作方式,您配置引擎并构建HTML,CakePDF完成其余的工作。嗯,就是这样。瑞典人:)当我将一个名为“pdf”的新文件夹添加到我的模板目录(如CakePDF文档中所述)时,哪个URL将引导我找到呈现的pdf?常规路由看起来像localhost/projectname/controller/action。通往PDF的路线如何?@Leyla Check。启用请求处理程序后,只需追加
.pdf
好!(小心!有时我们会被类中的异常抛出。所以我必须在重置编码之前尝试捕获)