PHP V5.3 中的新特性,…

本文探讨了PHP V5.3中的闭包和Lambda函数的应用,包括其历史背景、基本概念、与面向对象编程的整合方式以及如何利用反射API进行动态创建和内省。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://www.ibm.com/developerworks/cn/opensource/os-php-5.3new2/index.html

闭包函数和 lambda 函数绝对不是新出现的概念;它们均来自函数编程领域。函数编程 是一种编程风格,它将关注点从执行命令转移到表达式计算。这些表达式是使用函数构成的,结合这些函数可以得到我们要查找的结果。这种编程风格最常用于学术 目的,但是也可以在人工智能与数学领域中见到,并且可以在用 Erlang、Haskell 及 Scheme 等语言编写的商业应用程序中找到。

闭包 最初是在 20 世纪 60 年代作为 Scheme 的一部分开发的,Scheme 是最著名的函数编程语言之一。Lambda 函数和闭包通常出现在允许将函数处理为第一类值(First-class value)的语言中,这意味着函数可以动态创建并作为参数传递给其他语言。

从那时起,闭包及 lambda 函数已经找到了走出函数编程世界并进入 JavaScript、Python 和 Ruby 等语言的方法。JavaScript 是支持闭包和 lambda 函数的最常见语言之一。JavaScript 实际使用这些函数作为支持面向对象的编程方法,把函数嵌套到其他函数中以用作私有成员。清单 1 提供了 JavaScript 如何使用闭包的示例。



清单 1. 使用闭包构建 JavaScript 对象


var Example = function()
{ 
    this.public = function() 
    { 
        return "This is a public method"; 
    }; 

    var private = function() 
    { 
        return "This is a private method"; 
    };
};

Example.public()  // returns "This is a public method" 
Example.private() // error - doesn't work

如清单 1 中所示,Example 对象的成员函数被定义为闭包。由于私有方法作用于局部变量(与绑定到使用此关键字的 Example 对象的公共方法相反),因此从外部看不到它。

现在我们已经了解了这些概念的历史,让我们查看 PHP 中的 lambda 函数。lambda 函数的概念是闭包的基础,并且提供了一种比 PHP 中已有的 create_function() 函数改进了很多的动态创建函数的方法。

Lambda 函数

Lambda 函数(或者通常所谓的 “匿名函数”)是可以随时定义的简单抛弃型函数,并且通常都与变量绑定。函数本身仅存在于定义函数的变量范围内,因此当该变量超出范围时,函数也超出范 围。lambda 函数的理念源于 20 世纪 30 年代的数学研究。它被称为 lambda 演算,用于研究函数定义与应用程序以及递归概念。lambda 演算用于开发函数编程语言,例如 Lisp 和 Scheme。

对于大多数实例来说,尤其对于接受回调函数的许多 PHP 函数来说,Lambda 函数非常方便。array_map() 就是这样一种函数,它允许我们遍历数组并将回调函数应用到数组的每个元素上。在早期版本的 PHP 中,这些函数的最大问题是没有一种清晰的方式定义回调函数;我们坚持使用以下三种解决方法的其中一种:

  1. 我们可以在代码中的其他位置定义回调函数,因此我们知道它可用。这有些麻烦,因为它把调用的实现部分移到了其他位置,这样做对于可读性与可维护性极为不便,尤其是不打算在其他位置使用此函数时。
  2. 我们可以在同一个代码块中定义回调函数,但是使用一个名称。虽然这样做有助于把内容放在一起,但是需要在定义周围添加 if 块以避免名称空间冲突。清单 2 展示了这种方法。


    清单 2. 在同一个代码块中定义指定的回调
                                             
    function quoteWords()
    {
         if (!function_exists ('quoteWordsHelper')) {
             function quoteWordsHelper($string) {
                 return preg_replace('/(\w)/','"$1"',$string);
             }
          }
          return array_map('quoteWordsHelper', $text);
    }
    

  3. 我们可以使用 create_function()(从 V4 开始就是 PHP 的一部分)在运行时创建函数。虽然在功能上此函数执行了所需操作,但是它有一些缺点。一个主要缺点是,它在运行时而非编译时编译,不允许操作码缓存来缓存 函数。它的语法智能(syntax-wise)也非常糟糕,并且大多数 IDE 中的字符串高亮显示功能完全不起作用。

虽然接受回调函数的函数功能十分强大,但是没有一种好方法可以执行一次性回调函数,而无需执行一些非常笨拙的工作。使用 PHP V5.3,我们可以使用 lambda 函数以更规则的方法重新执行以上示例。


清单 3. 使用 lambda 函数用于回调的 quoteWords()

                            
function quoteWords()
{

     return array_map('quoteWordsHelper', function ($string) { return preg_replace('/(\w)/','"$1"',$string); }); }

我们看到了定义这些函数的更规则的语法,这可以通过操作码缓存来优化性能。我们也已经得到了改进的可读性以及与字符串高亮显示功能的兼容性。让我们在此基础上了解如何在 PHP 中使用闭包。

回页首

闭包

Lambda 函数本身并没有添加以前不能执行的功能。正如我们所见,我们可以使用 create_function() 执行所有这项操作,尽管后果是使用更糟糕的语法并且性能更加不理想。但是它们仍然是抛弃型函数并且不维护任何类型的状态,这限制了我们可以用它们执行的操作。因此出现了闭包并使 lambda 函数得到增强。

闭包是在它自己的环境中执行计算的函数,它有一个或多个绑定变量可以在调用函数时访问。它们来自函数编程世界,其中涉及大量概念。闭包类似于 lambda 函数,但是在与定义闭包的外部环境中的变量进行交互方面更加智能。

让我们看一看如何在 PHP 中定义闭包。清单 4 显示了从外部环境导入变量并将其简单地输出到屏幕上的闭包示例。


清单 4. 简单闭包示例
                            
$string = "Hello World!";
$closure = function() use ($string) { echo $string; };

$closure();

Output:
Hello World!

从外部环境中导入的变量是在闭包函数定义的 use 子句中指定的。默认情况下,它们是由值传递的,意味着如果要更新传递到闭包函数定义内的值,则不更新外部值。但是,我们可以通过在变量前放置 & 运算符来完成此操作,这种方法在函数定义中用于表示按引用传递。清单 5 显示了这种方法的示例。


清单 5. 通过引用传递变量的闭包
                               
$x = 1
$closure = function() use (&$x) { ++$x; }

echo $x . "\n";
$closure();
echo $x . "\n";
$closure();
echo $x . "\n";

Output:
1
2
3

可以看到,闭包使用外部变量 $x 并在每次调用闭包时递增该变量。我们可以将按值和按引用传递的变量轻松地混合到 use 子句中,并且可以顺利地处理这些变量。我们也可以拥有直接返回闭包的函数,如清单 6 所示。在本例中,闭包的生命周期实际上比定义闭包的方法长。


清单 6. 函数返回的闭包
                           
function getAppender($baseString)
{
      return function($appendString) use ($baseString) { return $baseString . 
$appendString; };
}

回页首

闭包与对象

闭包不但是过程式编程的有用工具,而且是面向对象编程的有用工具。在这种情况下使用闭包与在类外部使用闭包实现的目的相同:包含在小范围内绑定的特定函数。在对象外部与在对象内部使用一样简单。

在对象内定义时,非常方便的一点是闭包通过 $this 变量拥有对对象的完全访问权,而无需显式导入。清单 7 演示了该示例。


清单 7. 对象内的闭包
                            
class Dog
{
    private $_name;
    protected $_color;

    public function __construct($name, $color)
    {
         $this->_name = $name;
         $this->_color = $color;
    }

    public function greet($greeting)
    {
         return function() use ($greeting) {
             echo "$greeting, I am a {$this->_color} dog named 
{$this->_name}.";
         };
    }
}

$dog = new Dog("Rover","red");
$dog->greet("Hello");

Output:
Hello, I am a red dog named Rover.

在这里,我们在闭包内显式使用提供给 greet() 方法的欢迎词,闭包在该方法内定义。我们还在闭包内获取狗的颜色和名字,传递到构造函数中并存储到对象中。

在类中定义的闭包基本上与在对象外部定义的闭包相同。惟一的不同之处在于通过 $this 变量自动导入对象。我们可以通过将闭包定义为静态闭包禁用此行为。


清单 8. 静态闭包
                              
class House
{
     public function paint($color)
     {
         return static function() use ($color) { echo "Painting the 
house $color...."; };
     }
}

$house = new House();
$house->paint('red');

Output:
Painting the house red....

此示例类似于清单 5 中定义的 Dog 类。最大的差别是在闭包内不使用对象的任何属性,因为它被定义为静态类。

在对象内使用静态闭包与使用非静态闭包相比的最大优点是节省内存。由于无需将对象导入闭包中,因此可以节省大量内存,尤其是在拥有许多不需要此功能的闭包时。

针对对象的另一个优点是添加名为 __invoke() 的魔术方法,此方法允许对象本身被调用为闭包。如果定义了此方法,则在该上下文中调用对象时将使用此方法。清单 9 演示了示例。


清单 9. 使用 __invoke() 方法
                             

class Dog
{
    public function __invoke()
    {
         echo "I am a dog!";
    }
}

$dog = new Dog();
$dog();

将清单 9 中所示的对象引用调用为变量将自动调用 __invoke() 魔术方法,使类本身用作闭包。

闭包可以很好地与面向对象的代码以及面向过程的代码整合。让我们看一看闭包如何与 PHP 的强大 Reflection API 交互。

回页首

闭包与反射

PHP 有一个有用的反射 API,它允许我们对类、接口、函数和方法执行反向工程。按照设计,闭包是匿名函数,这意味着它们不显示在反射 API 中。

但是,新 getClosure() 方法已经添加到 PHP 中的 ReflectionMethodReflectionFunction 类中,可以从指定的函数或方法动态创建闭包。它在此上下文中用作宏,通过闭包调用函数方法将在定义它的上下文中执行函数调用。清单 10 显示了此方法如何运行。


清单 10. 使用 getClosure() 方法
                          
class Counter
{
      private $x;

      public function __construct()
      {
           $this->x = 0;
      }

      public function increment()
      {
           $this->x++;
      }

      public function currentValue()
      {
           echo $this->x . "\n";
      }
}
$class = new ReflectionClass('Counter');
$method = $class->getMethod('currentValue');
$closure = $method->getClosure()
$closure();
$class->increment();
$closure();
Output:
0
1

这种方法的一个有趣的副作用是允许通过闭包访问类的私有成员和受保护成员,这有利于对类执行单元测试。清单 11 展示了对类的私有方法的访问。


清单 11. 访问类的私有方法
                         
class Example 
{ 
     ....
     private static function secret() 
     { 
          echo "I'm an method that's hiding!"; 
     } 
     ...
} 

$class = new ReflectionClass('Example');
$method = $class->getMethod('secret');
$closure = $method->getClosure()
$closure();
Output:
I'm an method that's hiding!

此外,可以使用反射 API 来内省(introspect)闭包本身,如清单 12 所示。只需将对闭包的变量引用传递到 ReflectionMethod 类的构造函数中。


清单 12. 使用反射 API 内省闭包
                            
$closure = function ($x, $y = 1) {}; 
$m = new ReflectionMethod($closure); 
Reflection::export ($m);
Output:
Method [  public method __invoke ] {
  - Parameters [2] {
    Parameter #0 [  $x ]
    Parameter #1 [  $y ]
  }
}

关于向后兼容性值得注意的一点是,PHP 引擎现在保留类名 Closure 并用于存储闭包,因此使用该名称的所有类都需要重命名。

正如我们所见,反射 API 能够通过现有函数和方法动态创建闭包,从而为闭包提供强大的支持。它们还可以像普通函数一样内省到闭包中。

回页首

为什么使用闭包?

如在 lambda 函数的示例中所示,闭包的最明显用法之一是少数 PHP 函数接受回调函数作为参数。但是,在需要把逻辑封装到自己的范围内的情况下,闭包会十分有用。重构旧代码以进行简化并提高可读性就是这样一个例子。查看以 下示例,该示例显示了在运行一些 SQL 查询时使用的记录程序。


清单 13. 记录 SQL 查询的代码
                             
$db = mysqli_connect("server","user","pass"); 
Logger::log('debug','database','Connected to database'); 
$db->query('insert into parts (part, description) values ('Hammer','Pounds nails'); 
Logger::log('debug','database','Insert Hammer into to parts table'); 
$db->query('insert into parts (part, description) values 
      ('Drill','Puts holes in wood');
Logger::log('debug','database','Insert Drill into to parts table'); 
$db->query('insert into parts (part, description) values ('Saw','Cuts wood'); 
Logger::log('debug','database','Insert Saw into to parts table'); 

从清单 13 中可以看出执行操作的重复程度。对 Logger::log() 执行的每次调用都有相同的前两个实参。为了解决此问题,我们可以把该方法调用放入闭包并转而针对该闭包执行调用。得到的代码如下所示:


清单 14. 记录 SQL 查询的重构代码
                           
$logdb = function ($string) { Logger::log('debug','database',$string); };
$db = mysqli_connect("server","user","pass"); 
$logdb('Connected to database'); 
$db->query('insert into parts (part, description) values ('Hammer','Pounds nails'); 
$logdb('Insert Hammer into to parts table'); 
$db->query('insert into parts (part, description) values 
       ('Drill','Puts holes in wood');
$logdb('Insert Drill into to parts table'); 
$db->query('insert into parts (part, description) values ('Saw','Cuts wood'); 
$logdb('Insert Saw into to parts table'); 

代码不但在外观上更加规则,而且更易于更改 SQL 查询日志的日志级别,因为现在只需要在一个位置进行更改。

回页首

结束语

本文演示了闭包在 PHP V5.3 代码中作为函数编程构造时多么有用。我们讨论了 lambda 函数及闭包与这些函数相比的优点。对象与闭包可以很好地结合使用,比如我们在面向对象的代码内对闭包的特殊处理。我们看到了如何使用反射 API 创建动态闭包,以及如何内省现有的闭包。

<?php /** * 鸿宇多用户商城 模版类 * ============================================================================ * 版权所有 2005-2010 鸿宇多用户商城科技有限公司,并保留所有权利。 * 网站地址: http://bbs.hongyuvip.com; * ---------------------------------------------------------------------------- * 仅供学习交流使用,如需商用请购买正版版权。鸿宇不承担任何法律责任。 * 踏踏实实做事,堂堂正正做人。 * ============================================================================ * $Author: liuhui $ * $Id: cls_template.php 17063 2010-03-25 06:35:46Z liuhui $ */ class cls_template { var $template_dir = &#39;&#39;; var $cache_dir = &#39;&#39;; var $compile_dir = &#39;&#39;; var $cache_lifetime = 3600; // 缓存更新时间, 默认 3600 秒 var $direct_output = false; var $caching = false; var $template = array(); var $force_compile = false; var $_var = array(); var $_echash = &#39;554fcae493e564ee0dc75bdf2ebf94ca&#39;; var $_foreach = array(); var $_current_file = &#39;&#39;; var $_expires = 0; var $_errorlevel = 0; var $_nowtime = null; var $_checkfile = true; var $_foreachmark = &#39;&#39;; var $_seterror = 0; var $_temp_key = array(); // 临时存放 foreach 里 key 的数组 var $_temp_val = array(); // 临时存放 foreach 里 item 的数组 function __construct() { $this->cls_template(); } function cls_template() { $this->_errorlevel = error_reporting(); $this->_nowtime = time(); if (defined(&#39;EC_CHARSET&#39;)) { $charset = EC_CHARSET; } else { $charset = &#39;utf-8&#39;; } header(&#39;Content-type: text/html; charset=&#39;.$charset); } /** * 注册变量 * * @access public * @param mix $tpl_var * @param mix $value * * @return void */ function assign($tpl_var, $value = &#39;&#39;) { if (is_array($tpl_var)) { foreach ($tpl_var AS $key => $val) { if ($key != &#39;&#39;) { $this->_var[$key] = $val; } } } else { if ($tpl_var != &#39;&#39;) { $this->_var[$tpl_var] = $value; } } } /** * 显示页面函数 * * @access public * @param string $filename * @param sting $cache_id * * @return void */ function display($filename, $cache_id = &#39;&#39;) { $this->_seterror++; error_reporting(E_ALL ^ E_NOTICE); $this->_checkfile = false; $out = $this->fetch($filename, $cache_id); if (strpos($out, $this->_echash) !== false) { $k = explode($this->_echash, $out); foreach ($k AS $key => $val) { if (($key % 2) == 1) { $k[$key] = $this->insert_mod($val); } } $out = implode(&#39;&#39;, $k); } error_reporting($this->_errorlevel); $this->_seterror--; echo $out; } /** * 处理模板文件 * * @access public * @param string $filename * @param sting $cache_id * * @return sring */ function fetch($filename, $cache_id = &#39;&#39;) { if (!$this->_seterror) { error_reporting(E_ALL ^ E_NOTICE); } $this->_seterror++; if (strncmp($filename,&#39;str:&#39;, 4) == 0) { $out = $this->_eval($this->fetch_str(substr($filename, 4))); } else { if ($this->_checkfile) { if (!file_exists($filename)) { $filename = $this->template_dir . &#39;/&#39; . $filename; } } else { $filename = $this->template_dir . &#39;/&#39; . $filename; } if ($this->direct_output) { $this->_current_file = $filename; $out = $this->_eval($this->fetch_str(file_get_contents($filename))); } else { if ($cache_id && $this->caching) { $out = $this->template_out; } else { if (!in_array($filename, $this->template)) { $this->template[] = $filename; } $out = $this->make_compiled($filename); if ($cache_id) { $cachename = basename($filename, strrchr($filename, &#39;.&#39;)) . &#39;_&#39; . $cache_id; $data = serialize(array(&#39;template&#39; => $this->template, &#39;expires&#39; => $this->_nowtime + $this->cache_lifetime, &#39;maketime&#39; => $this->_nowtime)); $out = str_replace("\r", &#39;&#39;, $out); while (strpos($out, "\n\n") !== false) { $out = str_replace("\n\n", "\n", $out); } $hash_dir = $this->cache_dir . &#39;/&#39; . substr(md5($cachename), 0, 1); if (!is_dir($hash_dir)) { mkdir($hash_dir); } if (file_put_contents($hash_dir . &#39;/&#39; . $cachename . &#39;.php&#39;, &#39;<?php exit;?>&#39; . $data . $out, LOCK_EX) === false) { trigger_error(&#39;can\&#39;t write:&#39; . $hash_dir . &#39;/&#39; . $cachename . &#39;.php&#39;); } $this->template = array(); } } } } $this->_seterror--; if (!$this->_seterror) { error_reporting($this->_errorlevel); } return $out; // 返回html数据 } /** * 编译模板函数 * * @access public * @param string $filename * * @return sring 编译后文件地址 */ function make_compiled($filename) { $name = $this->compile_dir . &#39;/&#39; . basename($filename) . &#39;.php&#39;; if ($this->_expires) { $expires = $this->_expires - $this->cache_lifetime; } else { $filestat = @stat($name); $expires = $filestat[&#39;mtime&#39;]; } $filestat = @stat($filename); if ($filestat[&#39;mtime&#39;] <= $expires && !$this->force_compile) { if (file_exists($name)) { $source = $this->_require($name); if ($source == &#39;&#39;) { $expires = 0; } } else { $source = &#39;&#39;; $expires = 0; } } if ($this->force_compile || $filestat[&#39;mtime&#39;] > $expires) { $this->_current_file = $filename; $source = $this->fetch_str(file_get_contents($filename)); if (file_put_contents($name, $source, LOCK_EX) === false) { trigger_error(&#39;can\&#39;t write:&#39; . $name); } $source = $this->_eval($source); } return $source; } /** * 处理字符串函数 * * @access public * @param string $source * * @return sring */ function fetch_str($source) { if (!defined(&#39;ECS_ADMIN&#39;)) { $source = $this->smarty_prefilter_preCompile($source); } $source = preg_replace("/<\?[^><]+\?>|<\%[^><]+\%>|<script[^>]+language[^>]*=[^>]*php[^>]*>[^><]*<\/script\s*>/iU", "", $source); return preg_replace("/{([^\}\{\n]*)}/e", "\$this->select(&#39;\\1&#39;);", $source); } /** * 判断是否缓存 * * @access public * @param string $filename * @param sting $cache_id * * @return bool */ function is_cached($filename, $cache_id = &#39;&#39;) { $cachename = basename($filename, strrchr($filename, &#39;.&#39;)) . &#39;_&#39; . $cache_id; if ($this->caching == true && $this->direct_output == false) { $hash_dir = $this->cache_dir . &#39;/&#39; . substr(md5($cachename), 0, 1); if ($data = @file_get_contents($hash_dir . &#39;/&#39; . $cachename . &#39;.php&#39;)) { $data = substr($data, 13); $pos = strpos($data, &#39;<&#39;); $paradata = substr($data, 0, $pos); $para = @unserialize($paradata); if ($para === false || $this->_nowtime > $para[&#39;expires&#39;]) { $this->caching = false; return false; } $this->_expires = $para[&#39;expires&#39;]; $this->template_out = substr($data, $pos); foreach ($para[&#39;template&#39;] AS $val) { $stat = @stat($val); if ($para[&#39;maketime&#39;] < $stat[&#39;mtime&#39;]) { $this->caching = false; return false; } } } else { $this->caching = false; return false; } return true; } else { return false; } } /** * 处理{}标签 * * @access public * @param string $tag * * @return sring */ function select($tag) { $tag = stripslashes(trim($tag)); if (empty($tag)) { return &#39;{}&#39;; } elseif ($tag{0} == &#39;*&#39; && substr($tag, -1) == &#39;*&#39;) // 注释部分 { return &#39;&#39;; } elseif ($tag{0} == &#39;$&#39;) // 变量 { return &#39;<?php echo &#39; . $this->get_val(substr($tag, 1)) . &#39;; ?>&#39;; } elseif ($tag{0} == &#39;/&#39;) // 结束 tag { switch (substr($tag, 1)) { case &#39;if&#39;: return &#39;<?php endif; ?>&#39;; break; case &#39;foreach&#39;: if ($this->_foreachmark == &#39;foreachelse&#39;) { $output = &#39;<?php endif; unset($_from); ?>&#39;; } else { array_pop($this->_patchstack); $output = &#39;<?php endforeach; endif; unset($_from); ?>&#39;; } $output .= "<?php \$this->pop_vars();; ?>"; return $output; break; case &#39;literal&#39;: return &#39;&#39;; break; default: return &#39;{&#39;. $tag .&#39;}&#39;; break; } } else { /* 代码修改_start By bbs.hongyuvip.com */ //$tag_sel = array_shift(explode(&#39; &#39;, $tag)); $tag_arr_www_ecshop68_com = explode(&#39; &#39;, $tag); $tag_sel = array_shift($tag_arr_www_ecshop68_com); /* 代码修改_end By bbs.hongyuvip.com */ switch ($tag_sel) { case &#39;if&#39;: return $this->_compile_if_tag(substr($tag, 3)); break; case &#39;else&#39;: return &#39;<?php else: ?>&#39;; break; case &#39;elseif&#39;: return $this->_compile_if_tag(substr($tag, 7), true); break; case &#39;foreachelse&#39;: $this->_foreachmark = &#39;foreachelse&#39;; return &#39;<?php endforeach; else: ?>&#39;; break; case &#39;foreach&#39;: $this->_foreachmark = &#39;foreach&#39;; if(!isset($this->_patchstack)) { $this->_patchstack = array(); } return $this->_compile_foreach_start(substr($tag, 8)); break; case &#39;assign&#39;: $t = $this->get_para(substr($tag, 7),0); if ($t[&#39;value&#39;]{0} == &#39;$&#39;) { /* 如果传进来的值是变量,就不用用引号 */ $tmp = &#39;$this->assign(\&#39;&#39; . $t[&#39;var&#39;] . &#39;\&#39;,&#39; . $t[&#39;value&#39;] . &#39;);&#39;; } else { $tmp = &#39;$this->assign(\&#39;&#39; . $t[&#39;var&#39;] . &#39;\&#39;,\&#39;&#39; . addcslashes($t[&#39;value&#39;], "&#39;") . &#39;\&#39;);&#39;; } // $tmp = $this->assign($t[&#39;var&#39;], $t[&#39;value&#39;]); return &#39;<?php &#39; . $tmp . &#39; ?>&#39;; break; case &#39;include&#39;: $t = $this->get_para(substr($tag, 8), 0); return &#39;<?php echo $this->fetch(&#39; . "&#39;$t[file]&#39;" . &#39;); ?>&#39;; break; case &#39;insert_scripts&#39;: $t = $this->get_para(substr($tag, 15), 0); return &#39;<?php echo $this->smarty_insert_scripts(&#39; . $this->make_array($t) . &#39;); ?>&#39;; break; case &#39;create_pages&#39;: $t = $this->get_para(substr($tag, 13), 0); return &#39;<?php echo $this->smarty_create_pages(&#39; . $this->make_array($t) . &#39;); ?>&#39;; break; case &#39;insert&#39; : $t = $this->get_para(substr($tag, 7), false); $out = "<?php \n" . &#39;$k = &#39; . preg_replace("/(\&#39;\\$[^,]+)/e" , "stripslashes(trim(&#39;\\1&#39;,&#39;\&#39;&#39;));", var_export($t, true)) . ";\n"; $out .= &#39;echo $this->_echash . $k[\&#39;name\&#39;] . \&#39;|\&#39; . serialize($k) . $this->_echash;&#39; . "\n?>"; return $out; break; case &#39;literal&#39;: return &#39;&#39;; break; case &#39;cycle&#39; : $t = $this->get_para(substr($tag, 6), 0); return &#39;<?php echo $this->cycle(&#39; . $this->make_array($t) . &#39;); ?>&#39;; break; case &#39;html_options&#39;: $t = $this->get_para(substr($tag, 13), 0); return &#39;<?php echo $this->html_options(&#39; . $this->make_array($t) . &#39;); ?>&#39;; break; case &#39;html_select_date&#39;: $t = $this->get_para(substr($tag, 17), 0); return &#39;<?php echo $this->html_select_date(&#39; . $this->make_array($t) . &#39;); ?>&#39;; break; case &#39;html_radios&#39;: $t = $this->get_para(substr($tag, 12), 0); return &#39;<?php echo $this->html_radios(&#39; . $this->make_array($t) . &#39;); ?>&#39;; break; case &#39;html_select_time&#39;: $t = $this->get_para(substr($tag, 12), 0); return &#39;<?php echo $this->html_select_time(&#39; . $this->make_array($t) . &#39;); ?>&#39;; break; default: return &#39;{&#39; . $tag . &#39;}&#39;; break; } } } /** * 处理smarty标签中的变量标签 * * @access public * @param string $val * * @return bool */ function get_val($val) { if (strrpos($val, &#39;[&#39;) !== false) { $val = preg_replace("/\[([^\[\]]*)\]/eis", "&#39;.&#39;.str_replace(&#39;$&#39;,&#39;\$&#39;,&#39;\\1&#39;)", $val); } if (strrpos($val, &#39;|&#39;) !== false) { $moddb = explode(&#39;|&#39;, $val); $val = array_shift($moddb); } if (empty($val)) { return &#39;&#39;; } if (strpos($val, &#39;.$&#39;) !== false) { $all = explode(&#39;.$&#39;, $val); foreach ($all AS $key => $val) { $all[$key] = $key == 0 ? $this->make_var($val) : &#39;[&#39;. $this->make_var($val) . &#39;]&#39;; } $p = implode(&#39;&#39;, $all); } else { $p = $this->make_var($val); } if (!empty($moddb)) { foreach ($moddb AS $key => $mod) { $s = explode(&#39;:&#39;, $mod); switch ($s[0]) { case &#39;escape&#39;: $s[1] = trim($s[1], &#39;"&#39;); if ($s[1] == &#39;html&#39;) { $p = &#39;htmlspecialchars(&#39; . $p . &#39;)&#39;; } elseif ($s[1] == &#39;url&#39;) { $p = &#39;urlencode(&#39; . $p . &#39;)&#39;; } elseif ($s[1] == &#39;decode_url&#39;) { $p = &#39;urldecode(&#39; . $p . &#39;)&#39;; } elseif ($s[1] == &#39;quotes&#39;) { $p = &#39;addslashes(&#39; . $p . &#39;)&#39;; } elseif ($s[1] == &#39;u8_url&#39;) { if (EC_CHARSET != &#39;utf-8&#39;) { $p = &#39;urlencode(ecs_iconv("&#39; . EC_CHARSET . &#39;", "utf-8",&#39; . $p . &#39;))&#39;; } else { $p = &#39;urlencode(&#39; . $p . &#39;)&#39;; } } else { $p = &#39;htmlspecialchars(&#39; . $p . &#39;)&#39;; } break; case &#39;nl2br&#39;: $p = &#39;nl2br(&#39; . $p . &#39;)&#39;; break; case &#39;default&#39;: $s[1] = $s[1]{0} == &#39;$&#39; ? $this->get_val(substr($s[1], 1)) : "&#39;$s[1]&#39;"; $p = &#39;empty(&#39; . $p . &#39;) ? &#39; . $s[1] . &#39; : &#39; . $p; break; case &#39;truncate&#39;: $p = &#39;sub_str(&#39; . $p . ",$s[1])"; break; case &#39;strip_tags&#39;: $p = &#39;strip_tags(&#39; . $p . &#39;)&#39;; break; default: # code... break; } } } return $p; } /** * 处理去掉$的字符串 * * @access public * @param string $val * * @return bool */ function make_var($val) { if (strrpos($val, &#39;.&#39;) === false) { if (isset($this->_var[$val]) && isset($this->_patchstack[$val])) { $val = $this->_patchstack[$val]; } $p = &#39;$this->_var[\&#39;&#39; . $val . &#39;\&#39;]&#39;; } else { $t = explode(&#39;.&#39;, $val); $_var_name = array_shift($t); if (isset($this->_var[$_var_name]) && isset($this->_patchstack[$_var_name])) { $_var_name = $this->_patchstack[$_var_name]; } if ($_var_name == &#39;smarty&#39;) { $p = $this->_compile_smarty_ref($t); } else { $p = &#39;$this->_var[\&#39;&#39; . $_var_name . &#39;\&#39;]&#39;; } foreach ($t AS $val) { $p.= &#39;[\&#39;&#39; . $val . &#39;\&#39;]&#39;; } } return $p; } /** * 处理insert外部函数/需要include运行的函数的调用数据 * * @access public * @param string $val * @param int $type * * @return array */ function get_para($val, $type = 1) // 处理insert外部函数/需要include运行的函数的调用数据 { $pa = $this->str_trim($val); foreach ($pa AS $value) { if (strrpos($value, &#39;=&#39;)) { list($a, $b) = explode(&#39;=&#39;, str_replace(array(&#39; &#39;, &#39;"&#39;, "&#39;", &#39;"&#39;), &#39;&#39;, $value)); if ($b{0} == &#39;$&#39;) { if ($type) { eval(&#39;$para[\&#39;&#39; . $a . &#39;\&#39;]=&#39; . $this->get_val(substr($b, 1)) . &#39;;&#39;); } else { $para[$a] = $this->get_val(substr($b, 1)); } } else { $para[$a] = $b; } } } return $para; } /** * 判断变量是否被注册并返回值 * * @access public * @param string $name * * @return mix */ function &get_template_vars($name = null) { if (empty($name)) { return $this->_var; } elseif (!empty($this->_var[$name])) { return $this->_var[$name]; } else { $_tmp = null; return $_tmp; } } /** * 处理if标签 * * @access public * @param string $tag_args * @param bool $elseif * * @return string */ function _compile_if_tag($tag_args, $elseif = false) { preg_match_all(&#39;/\-?\d+[\.\d]+|\&#39;[^\&#39;|\s]*\&#39;|"[^"|\s]*"|[\$\w\.]+|!==|===|==|!=|<>|<<|>>|<=|>=|&&|\|\||\(|\)|,|\!|\^|=|&|<|>|~|\||\%|\+|\-|\/|\*|\@|\S/&#39;, $tag_args, $match); $tokens = $match[0]; // make sure we have balanced parenthesis $token_count = array_count_values($tokens); if (!empty($token_count[&#39;(&#39;]) && $token_count[&#39;(&#39;] != $token_count[&#39;)&#39;]) { // $this->_syntax_error(&#39;unbalanced parenthesis in if statement&#39;, E_USER_ERROR, __FILE__, __LINE__); } for ($i = 0, $count = count($tokens); $i < $count; $i++) { $token = &$tokens[$i]; switch (strtolower($token)) { case &#39;eq&#39;: $token = &#39;==&#39;; break; case &#39;ne&#39;: case &#39;neq&#39;: $token = &#39;!=&#39;; break; case &#39;lt&#39;: $token = &#39;<&#39;; break; case &#39;le&#39;: case &#39;lte&#39;: $token = &#39;<=&#39;; break; case &#39;gt&#39;: $token = &#39;>&#39;; break; case &#39;ge&#39;: case &#39;gte&#39;: $token = &#39;>=&#39;; break; case &#39;and&#39;: $token = &#39;&&&#39;; break; case &#39;or&#39;: $token = &#39;||&#39;; break; case &#39;not&#39;: $token = &#39;!&#39;; break; case &#39;mod&#39;: $token = &#39;%&#39;; break; default: if ($token[0] == &#39;$&#39;) { $token = $this->get_val(substr($token, 1)); } break; } } if ($elseif) { return &#39;<?php elseif (&#39; . implode(&#39; &#39;, $tokens) . &#39;): ?>&#39;; } else { return &#39;<?php if (&#39; . implode(&#39; &#39;, $tokens) . &#39;): ?>&#39;; } } /** * 处理foreach标签 * * @access public * @param string $tag_args * * @return string */ function _compile_foreach_start($tag_args) { $attrs = $this->get_para($tag_args, 0); $arg_list = array(); $from = $attrs[&#39;from&#39;]; if(isset($this->_var[$attrs[&#39;item&#39;]]) && !isset($this->_patchstack[$attrs[&#39;item&#39;]])) { $this->_patchstack[$attrs[&#39;item&#39;]] = $attrs[&#39;item&#39;] . &#39;_&#39; . str_replace(array(&#39; &#39;, &#39;.&#39;), &#39;_&#39;, microtime()); $attrs[&#39;item&#39;] = $this->_patchstack[$attrs[&#39;item&#39;]]; } else { $this->_patchstack[$attrs[&#39;item&#39;]] = $attrs[&#39;item&#39;]; } $item = $this->get_val($attrs[&#39;item&#39;]); if (!empty($attrs[&#39;key&#39;])) { $key = $attrs[&#39;key&#39;]; $key_part = $this->get_val($key).&#39; => &#39;; } else { $key = null; $key_part = &#39;&#39;; } if (!empty($attrs[&#39;name&#39;])) { $name = $attrs[&#39;name&#39;]; } else { $name = null; } $output = &#39;<?php &#39;; $output .= "\$_from = $from; if (!is_array(\$_from) && !is_object(\$_from)) { settype(\$_from, &#39;array&#39;); }; \$this->push_vars(&#39;$attrs[key]&#39;, &#39;$attrs[item]&#39;);"; if (!empty($name)) { $foreach_props = "\$this->_foreach[&#39;$name&#39;]"; $output .= "{$foreach_props} = array(&#39;total&#39; => count(\$_from), &#39;iteration&#39; => 0);\n"; $output .= "if ({$foreach_props}[&#39;total&#39;] > 0):\n"; $output .= " foreach (\$_from AS $key_part$item):\n"; $output .= " {$foreach_props}[&#39;iteration&#39;]++;\n"; } else { $output .= "if (count(\$_from)):\n"; $output .= " foreach (\$_from AS $key_part$item):\n"; } return $output . &#39;?>&#39;; } /** * 将 foreach 的 key, item 放入临时数组 * * @param mixed $key * @param mixed $val * * @return void */ function push_vars($key, $val) { if (!empty($key)) { array_push($this->_temp_key, "\$this->_vars[&#39;$key&#39;]=&#39;" .$this->_vars[$key] . "&#39;;"); } if (!empty($val)) { array_push($this->_temp_val, "\$this->_vars[&#39;$val&#39;]=&#39;" .$this->_vars[$val] ."&#39;;"); } } /** * 弹出临时数组的最后一个 * * @return void */ function pop_vars() { $key = array_pop($this->_temp_key); $val = array_pop($this->_temp_val); if (!empty($key)) { eval($key); } } /** * 处理smarty开头的预定义变量 * * @access public * @param array $indexes * * @return string */ function _compile_smarty_ref(&$indexes) { /* Extract the reference name. */ $_ref = $indexes[0]; switch ($_ref) { case &#39;now&#39;: $compiled_ref = &#39;time()&#39;; break; case &#39;foreach&#39;: array_shift($indexes); $_var = $indexes[0]; $_propname = $indexes[1]; switch ($_propname) { case &#39;index&#39;: array_shift($indexes); $compiled_ref = "(\$this->_foreach[&#39;$_var&#39;][&#39;iteration&#39;] - 1)"; break; case &#39;first&#39;: array_shift($indexes); $compiled_ref = "(\$this->_foreach[&#39;$_var&#39;][&#39;iteration&#39;] <= 1)"; break; case &#39;last&#39;: array_shift($indexes); $compiled_ref = "(\$this->_foreach[&#39;$_var&#39;][&#39;iteration&#39;] == \$this->_foreach[&#39;$_var&#39;][&#39;total&#39;])"; break; case &#39;show&#39;: array_shift($indexes); $compiled_ref = "(\$this->_foreach[&#39;$_var&#39;][&#39;total&#39;] > 0)"; break; default: $compiled_ref = "\$this->_foreach[&#39;$_var&#39;]"; break; } break; case &#39;get&#39;: $compiled_ref = &#39;$_GET&#39;; break; case &#39;post&#39;: $compiled_ref = &#39;$_POST&#39;; break; case &#39;cookies&#39;: $compiled_ref = &#39;$_COOKIE&#39;; break; case &#39;env&#39;: $compiled_ref = &#39;$_ENV&#39;; break; case &#39;server&#39;: $compiled_ref = &#39;$_SERVER&#39;; break; case &#39;request&#39;: $compiled_ref = &#39;$_REQUEST&#39;; break; case &#39;session&#39;: $compiled_ref = &#39;$_SESSION&#39;; break; default: // $this->_syntax_error(&#39;$smarty.&#39; . $_ref . &#39; is an unknown reference&#39;, E_USER_ERROR, __FILE__, __LINE__); break; } array_shift($indexes); return $compiled_ref; } function smarty_insert_scripts($args) { static $scripts = array(); $arr = explode(&#39;,&#39;, str_replace(&#39; &#39;, &#39;&#39;, $args[&#39;files&#39;])); $str = &#39;&#39;; foreach ($arr AS $val) { if (in_array($val, $scripts) == false) { $scripts[] = $val; if ($val{0} == &#39;.&#39;) { $str .= &#39;<script type="text/javascript" src="&#39; . $val . &#39;"></script>&#39;; } else { $str .= &#39;<script type="text/javascript" src="js/&#39; . $val . &#39;"></script>&#39;; } } } return $str; } function smarty_prefilter_preCompile($source) { $file_type = strtolower(strrchr($this->_current_file, &#39;.&#39;)); $tmp_dir = &#39;themes/&#39; . $GLOBALS[&#39;_CFG&#39;][&#39;template&#39;] . &#39;/&#39;; // 模板所在路径 /** * 处理模板文件 */ if ($file_type == &#39;.dwt&#39;) { /* 将模板中所有library替换为链接 */ $pattern = &#39;/<!--\s#BeginLibraryItem\s\"\/(.*?)\"\s-->.*?<!--\s#EndLibraryItem\s-->/se&#39;; $replacement = "&#39;{include file=&#39;.strtolower(&#39;\\1&#39;). &#39;}&#39;"; $source = preg_replace($pattern, $replacement, $source); /* 检查有无动态库文件,如果有为其赋值 */ $dyna_libs = get_dyna_libs($GLOBALS[&#39;_CFG&#39;][&#39;template&#39;], $this->_current_file); if ($dyna_libs) { foreach ($dyna_libs AS $region => $libs) { $pattern = &#39;/<!--\\s*TemplateBeginEditable\\sname="&#39;. $region .&#39;"\\s*-->(.*?)<!--\\s*TemplateEndEditable\\s*-->/s&#39;; if (preg_match($pattern, $source, $reg_match)) { $reg_content = $reg_match[1]; /* 生成匹配字串 */ $keys = array_keys($libs); $lib_pattern = &#39;&#39;; foreach ($keys AS $lib) { $lib_pattern .= &#39;|&#39; . str_replace(&#39;/&#39;, &#39;\/&#39;, substr($lib, 1)); } $lib_pattern = &#39;/{include\sfile=(&#39; . substr($lib_pattern, 1) . &#39;)}/&#39;; /* 修改$reg_content中的内容 */ $GLOBALS[&#39;libs&#39;] = $libs; $reg_content = preg_replace_callback($lib_pattern, &#39;dyna_libs_replace&#39;, $reg_content); /* 用修改过的内容替换原来当前区域中内容 */ $source = preg_replace($pattern, $reg_content, $source); } } } /* 在头部加入版本信息 */ $source = preg_replace(&#39;/<head>/i&#39;, "<head>\r\n<meta name=\"Generator\" content=\"" . APPNAME .&#39; &#39; . VERSION . "\" />", $source); /* By bbs.hongyuvip.com 代码增加_start */ $source = preg_replace(&#39;/<head>/i&#39;, "<head>\r\n<base href=\"". $GLOBALS[&#39;ecs&#39;]->url() ."\" />", $source); /* By bbs.hongyuvip.com 代码增加_end */ /* 修正css路径 */ $source = preg_replace(&#39;/(<link\shref=["|\&#39;])(?:\.\/|\.\.\/)?(css\/)?([a-z0-9A-Z_]+\.css["|\&#39;]\srel=["|\&#39;]stylesheet["|\&#39;]\stype=["|\&#39;]text\/css["|\&#39;])/i&#39;,&#39;\1&#39; . $tmp_dir . &#39;\2\3&#39;, $source); /* 修正js目录下js的路径 */ $source = preg_replace(&#39;/(<script\s(?:type|language)=["|\&#39;]text\/javascript["|\&#39;]\ssrc=["|\&#39;])(?:\.\/|\.\.\/)?(js\/[a-z0-9A-Z_\-\.]+\.(?:js|vbs)["|\&#39;]><\/script>)/&#39;, &#39;\1&#39; . $tmp_dir . &#39;\2&#39;, $source); /* 更换编译模板的编码类型 */ $source = preg_replace(&#39;/<meta\shttp-equiv=["|\&#39;]Content-Type["|\&#39;]\scontent=["|\&#39;]text\/html;\scharset=(?:.*?)["|\&#39;][^>]*?>\r?\n?/i&#39;, &#39;<meta http-equiv="Content-Type" content="text/html; charset=&#39; . EC_CHARSET . &#39;" />&#39; . "\n", $source); } /** * 处理库文件 */ elseif ($file_type == &#39;.lbi&#39;) { /* 去除meta */ $source = preg_replace(&#39;/<meta\shttp-equiv=["|\&#39;]Content-Type["|\&#39;]\scontent=["|\&#39;]text\/html;\scharset=(?:.*?)["|\&#39;]>\r?\n?/i&#39;, &#39;&#39;, $source); } /* 替换文件编码头部 */ if (strpos($source, "\xEF\xBB\xBF") !== FALSE) { $source = str_replace("\xEF\xBB\xBF", &#39;&#39;, $source); } $pattern = array( &#39;/<!--[^>|\n]*?({.+?})[^<|{|\n]*?-->/&#39;, // 替换smarty注释 &#39;/<!--[^<|>|{|\n]*?-->/&#39;, // 替换不换行的html注释 &#39;/(href=["|\&#39;])\.\.\/(.*?)(["|\&#39;])/i&#39;, // 替换相对链接 &#39;/((?:background|src)\s*=\s*["|\&#39;])(?:\.\/|\.\.\/)?(images\/.*?["|\&#39;])/is&#39;, // 在images前加上 $tmp_dir &#39;/((?:background|background-image):\s*?url\()(?:\.\/|\.\.\/)?(images\/)/is&#39;, // 在images前加上 $tmp_dir &#39;/([\&#39;|"])\.\.\//is&#39;, // 以../开头的路径全部修正为空 ); $replace = array( &#39;\1&#39;, &#39;&#39;, &#39;\1\2\3&#39;, &#39;\1&#39; . $tmp_dir . &#39;\2&#39;, &#39;\1&#39; . $tmp_dir . &#39;\2&#39;, &#39;\1&#39; ); return preg_replace($pattern, $replace, $source); } function insert_mod($name) // 处理动态内容 { list($fun, $para) = explode(&#39;|&#39;, $name); $para = unserialize($para); $fun = &#39;insert_&#39; . $fun; return $fun($para); } function str_trim($str) { /* 处理&#39;a=b c=d k = f &#39;类字符串,返回数组 */ while (strpos($str, &#39;= &#39;) != 0) { $str = str_replace(&#39;= &#39;, &#39;=&#39;, $str); } while (strpos($str, &#39; =&#39;) != 0) { $str = str_replace(&#39; =&#39;, &#39;=&#39;, $str); } return explode(&#39; &#39;, trim($str)); } function _eval($content) { ob_start(); eval(&#39;?&#39; . &#39;>&#39; . trim($content)); $content = ob_get_contents(); ob_end_clean(); return $content; } function _require($filename) { ob_start(); include $filename; $content = ob_get_contents(); ob_end_clean(); return $content; } function html_options($arr) { $selected = $arr[&#39;selected&#39;]; if ($arr[&#39;options&#39;]) { $options = (array)$arr[&#39;options&#39;]; } elseif ($arr[&#39;output&#39;]) { if ($arr[&#39;values&#39;]) { foreach ($arr[&#39;output&#39;] AS $key => $val) { $options["{$arr[values][$key]}"] = $val; } } else { $options = array_values((array)$arr[&#39;output&#39;]); } } if ($options) { foreach ($options AS $key => $val) { $out .= $key == $selected ? "<option value=\"$key\" selected>$val</option>" : "<option value=\"$key\">$val</option>"; } } return $out; } function html_select_date($arr) { $pre = $arr[&#39;prefix&#39;]; if (isset($arr[&#39;time&#39;])) { if (intval($arr[&#39;time&#39;]) > 10000) { $arr[&#39;time&#39;] = gmdate(&#39;Y-m-d&#39;, $arr[&#39;time&#39;] + 8*3600); } $t = explode(&#39;-&#39;, $arr[&#39;time&#39;]); $year = strval($t[0]); $month = strval($t[1]); $day = strval($t[2]); } $now = gmdate(&#39;Y&#39;, $this->_nowtime); if (isset($arr[&#39;start_year&#39;])) { if (abs($arr[&#39;start_year&#39;]) == $arr[&#39;start_year&#39;]) { $startyear = $arr[&#39;start_year&#39;]; } else { $startyear = $arr[&#39;start_year&#39;] + $now; } } else { $startyear = $now - 3; } if (isset($arr[&#39;end_year&#39;])) { if (strlen(abs($arr[&#39;end_year&#39;])) == strlen($arr[&#39;end_year&#39;])) { $endyear = $arr[&#39;end_year&#39;]; } else { $endyear = $arr[&#39;end_year&#39;] + $now; } } else { $endyear = $now + 3; } $out = "<select name=\"{$pre}Year\">"; for ($i = $startyear; $i <= $endyear; $i++) { $out .= $i == $year ? "<option value=\"$i\" selected>$i</option>" : "<option value=\"$i\">$i</option>"; } if ($arr[&#39;display_months&#39;] != &#39;false&#39;) { $out .= "</select>&nbsp;<select name=\"{$pre}Month\">"; for ($i = 1; $i <= 12; $i++) { $out .= $i == $month ? "<option value=\"$i\" selected>" . str_pad($i, 2, &#39;0&#39;, STR_PAD_LEFT) . "</option>" : "<option value=\"$i\">" . str_pad($i, 2, &#39;0&#39;, STR_PAD_LEFT) . "</option>"; } } if ($arr[&#39;display_days&#39;] != &#39;false&#39;) { $out .= "</select>&nbsp;<select name=\"{$pre}Day\">"; for ($i = 1; $i <= 31; $i++) { $out .= $i == $day ? "<option value=\"$i\" selected>" . str_pad($i, 2, &#39;0&#39;, STR_PAD_LEFT) . "</option>" : "<option value=\"$i\">" . str_pad($i, 2, &#39;0&#39;, STR_PAD_LEFT) . "</option>"; } } return $out . &#39;</select>&#39;; } function html_radios($arr) { $name = $arr[&#39;name&#39;]; $checked = $arr[&#39;checked&#39;]; $options = $arr[&#39;options&#39;]; $out = &#39;&#39;; foreach ($options AS $key => $val) { $out .= $key == $checked ? "<input type=\"radio\" name=\"$name\" value=\"$key\" checked>&nbsp;{$val}&nbsp;" : "<input type=\"radio\" name=\"$name\" value=\"$key\">&nbsp;{$val}&nbsp;"; } return $out; } function html_select_time($arr) { $pre = $arr[&#39;prefix&#39;]; if (isset($arr[&#39;time&#39;])) { $arr[&#39;time&#39;] = gmdate(&#39;H-i-s&#39;, $arr[&#39;time&#39;] + 8*3600); $t = explode(&#39;-&#39;, $arr[&#39;time&#39;]); $hour = strval($t[0]); $minute = strval($t[1]); $second = strval($t[2]); } $out = &#39;&#39;; if (!isset($arr[&#39;display_hours&#39;])) { $out .= "<select name=\"{$pre}Hour\">"; for ($i = 0; $i <= 23; $i++) { $out .= $i == $hour ? "<option value=\"$i\" selected>" . str_pad($i, 2, &#39;0&#39;, STR_PAD_LEFT) . "</option>" : "<option value=\"$i\">" . str_pad($i, 2, &#39;0&#39;, STR_PAD_LEFT) . "</option>"; } $out .= "</select>&nbsp;"; } if (!isset($arr[&#39;display_minutes&#39;])) { $out .= "<select name=\"{$pre}Minute\">"; for ($i = 0; $i <= 59; $i++) { $out .= $i == $minute ? "<option value=\"$i\" selected>" . str_pad($i, 2, &#39;0&#39;, STR_PAD_LEFT) . "</option>" : "<option value=\"$i\">" . str_pad($i, 2, &#39;0&#39;, STR_PAD_LEFT) . "</option>"; } $out .= "</select>&nbsp;"; } if (!isset($arr[&#39;display_seconds&#39;])) { $out .= "<select name=\"{$pre}Second\">"; for ($i = 0; $i <= 59; $i++) { $out .= $i == $second ? "<option value=\"$i\" selected>" . str_pad($i, 2, &#39;0&#39;, STR_PAD_LEFT) . "</option>" : "<option value=\"$i\">$i</option>"; } $out .= "</select>&nbsp;"; } return $out; } function cycle($arr) { static $k, $old; $value = explode(&#39;,&#39;, $arr[&#39;values&#39;]); if ($old != $value) { $old = $value; $k = 0; } else { $k++; if (!isset($old[$k])) { $k = 0; } } echo $old[$k]; } function make_array($arr) { $out = &#39;&#39;; foreach ($arr AS $key => $val) { if ($val{0} == &#39;$&#39;) { $out .= $out ? ",&#39;$key&#39;=>$val" : "array(&#39;$key&#39;=>$val"; } else { $out .= $out ? ",&#39;$key&#39;=>&#39;$val&#39;" : "array(&#39;$key&#39;=>&#39;$val&#39;"; } } return $out . &#39;)&#39;; } function smarty_create_pages($params) { extract($params); if (empty($page)) { $page = 1; } if (!empty($count)) { $str = "<option value=&#39;1&#39;>1</option>"; $min = min($count - 1, $page + 3); for ($i = $page - 3 ; $i <= $min ; $i++) { if ($i < 2) { continue; } $str .= "<option value=&#39;$i&#39;"; $str .= $page == $i ? " selected=&#39;true&#39;" : &#39;&#39;; $str .= ">$i</option>"; } if ($count > 1) { $str .= "<option value=&#39;$count&#39;"; $str .= $page == $count ? " selected=&#39;true&#39;" : &#39;&#39;; $str .= ">$count</option>"; } } else { $str = &#39;&#39;; } return $str; } } ?> php5.3升级到php5.6 给一个完整版源码文件 包涵以前所有功能进行完整版修复
07-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值