Smarty returns 时不时出现一个空结果
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 总是 returns 一个空结果。例如,拿这个代码:
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";
这似乎与这个问题有关:
我的脚本做了很多事情,所以需要很长时间才能完成。一些用户在脚本完成之前关闭浏览器,这就是 Smarty returns 一个空结果,因为它经常使用 ob_start。
祝福,
无一例外地让页面空白似乎是聪明人做任何事情的方式..
我不熟悉 python,但是,我怀疑只抛出异常。没有通知。您可能会在代码末尾尝试检查抛出的通知或其他警告,无论它是在 python.
中调用的
可能还是文件夹权限,你也检查过templates_c目录是否存在,是否有权限?或任何没有 $.
的 {var.name}
它可以是任何东西,smarty 从不抛出异常,它只是让页面空白。
如果仍然没有帮助,创建一个基本的过于简化的模板,然后尝试一段时间,看看它是否仍然发生。如果是,则说明您的模板有误。
据我所知,这是 PHP 5.6 中的一个错误。我使用 print_r 进行了一些测试,并将 return 标志设置为 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,如果您调用脚本并关闭连接,则会抛出异常,因为 print_r return 结果为空。但是,使用 PHP 7.0 或 PHP 8.0 脚本将保持 运行 直到达到最大执行时间。
亲切的问候,
我在使用 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 总是 returns 一个空结果。例如,拿这个代码:
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";
这似乎与这个问题有关:
我的脚本做了很多事情,所以需要很长时间才能完成。一些用户在脚本完成之前关闭浏览器,这就是 Smarty returns 一个空结果,因为它经常使用 ob_start。
祝福,
无一例外地让页面空白似乎是聪明人做任何事情的方式..
我不熟悉 python,但是,我怀疑只抛出异常。没有通知。您可能会在代码末尾尝试检查抛出的通知或其他警告,无论它是在 python.
中调用的可能还是文件夹权限,你也检查过templates_c目录是否存在,是否有权限?或任何没有 $.
的 {var.name}它可以是任何东西,smarty 从不抛出异常,它只是让页面空白。
如果仍然没有帮助,创建一个基本的过于简化的模板,然后尝试一段时间,看看它是否仍然发生。如果是,则说明您的模板有误。
据我所知,这是 PHP 5.6 中的一个错误。我使用 print_r 进行了一些测试,并将 return 标志设置为 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,如果您调用脚本并关闭连接,则会抛出异常,因为 print_r return 结果为空。但是,使用 PHP 7.0 或 PHP 8.0 脚本将保持 运行 直到达到最大执行时间。
亲切的问候,