繁体   English   中英

Smarty 时不时地返回一个空结果

[英]Smarty returns an empty result every now and then

我在使用 Smarty 时遇到了一个奇怪的问题。 我正在通过模板生成电子邮件的正文。 大多数时候它按预期工作,但有时返回的数据是空的。 但是,我在日志中没有看到任何错误,也没有发现任何异常。 就好像模板是空的。

这是我用来获取电子邮件正文的一段代码:

// $data is an array with template's data
// $tpl is the template's path
$s = new Smarty();
$s->assignArray( $data );

try {
    $body = $s->fetch( $tpl );
} catch ( \Exception $e ) {
    Debug::Log( $e->getMessage() );
}

// Sometimes $body is empty, but no exception is thrown.

我检查了模板没有错误,毕竟它在大多数情况下都有效。

当 $body 为空时,我还保存了 $data 内容并手动运行代码以获取 $body 内容,但它有效,所以我认为问题与模板变量无关。

我做的另一个测试是尝试处理模板最多 5 次,在两次尝试之间休眠一秒钟,但结果总是空的。

模板的缓存路径是可写的。

我正在使用 PHP 5.6.40、Smarty 3.1.21 和 Apache2。

你能帮我调试一下这个问题吗?

更新

我已经能够重现该问题。 在 PHP 检测到客户端关闭连接后,每当调用 fetch 方法时,Smarty 总是返回一个空结果。 例如,使用以下代码:

ignore_user_abort(1); // Continue running even if the connection is closed
set_time_limit(180); // 3 minutes

$s = new Smarty();
$s->assignArray( $data );

// Keep writing data untill PHP realises that connection was closed
while( 1 ) {
    if(connection_status() != CONNECTION_NORMAL || connection_aborted( ) ) {
        break;
    }
    echo "123456789";
}

$body = $s->fetch( $tpl );
if ( '' == $body ) {
    throw new Exception("Result is empty");
}
die('Code never reaches this point');

如果我调用上面的脚本并立即关闭连接,则 fetch 方法的结果始终为空。

但是,如果 PHP 没有检测到连接已关闭,即使确实已关闭,则 fetch 的结果也不为空。

ignore_user_abort(1); // Continue running even if the connection is closed
set_time_limit(180); // 3 minutes

$s = new Smarty();
$s->assignArray( $data );

// Sleep to make sure the connection was closed
// PHP do not realise the connection is closed untill it tries to write something
sleep( 60);

$body = $s->fetch( $tpl );
if ( '' == $body ) {
    throw new Exception("Result is empty");
}

echo "Now the result is not empty";

这是我用来调用上述脚本的代码:

<?php
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,    'https://myhost/test.php');
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_exec($ch);
curl_close($ch);

echo "all done";

这似乎与这个问题有关: PHP ob_get_contents "sometimes" return empty when it should not?

我的脚本做了很多事情,所以需要很长时间才能完成。 一些用户在脚本完成之前关闭浏览器,这就是 Smarty 返回空结果的时候,因为它经常使用 ob_start。

最好的祝愿,

毫无例外地空白页面似乎是 smarty 做所有事情的方式。

我不熟悉 python,但是,我怀疑只会抛出异常。 不是通知。 您可以在代码末尾尝试检查抛出的通知或其他警告,但它在 python 中调用。

它可能仍然是文件夹权限,您是否还检查过 templates_c 目录是否存在,并且有操作? 或任何不带 $ 的 {var.name}。

它可以是任何东西,smarty 从不抛出异常,它只是使页面空白。

如果它仍然没有帮助,请创建一个基本的过于简化的模板,然后尝试一段时间,看看它是否仍然会发生。 如果是这样,那是您的模板中的错误。

就我而言,它原来是 PHP 5.6 中的一个错误。 我使用 print_r 进行了一些测试,返回标志设置为 true,关闭连接后的结果在 PHP 7.0 和 PHP 8.0 中永远不会为空。 但是,当我使用 PHP 5.6 时,结果为空。

例子:

<?php
error_reporting( E_ALL );
ini_set('display_errors', 1);
ignore_user_abort(true);// (curl disconnects after 1 second)
ini_set('max_execution_time','180');    // 3 minutes
ini_set('memory_limit','512M');         // 512 MB

function testPrint_r($length)
{
    $test1 = array('TEST'=>'SOMETHING');
    $test2 = print_r($test1, true);
    $test3 = "Array\n(\n    [TEST] => SOMETHING\n)\n";
    if(strcmp($test2, $test3)!==0) {
        throw new Exception("Print_r check failed, output length so far: ".$length);
        // consult your error.log then, or use some other reporting means
    }
}

$message = "123456789\n";
$length = strlen($message);
$total_length = 0;
while(1)
{
    echo $message;
    $total_length += $length;
    testPrint_r($total_length);
}
die('it should not get here');

使用 PHP 5.6,如果调用脚本并关闭连接,则会抛出 Exception,因为 print_r 返回一个空结果。 但是,使用 PHP 7.0 或 PHP 8.0 时,脚本会一直运行,直到达到最大执行时间。

亲切的问候,

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM