1

大约有一百万个 PHP 模板引擎(Blade、Twig、Smarty、Mustache,...),我只是讨厌创建新语法和编译器以在 HTML 中编写 PHP 的想法!我认为它只是不聪明(但这不是我在这里讨论的:)),以通常的方式编写 PHP+HTML 有什么问题 - 不是为了逻辑 - 你知道,所有的变量和循环并定义你想要使用没有这个 {{% %}} 或那个 {:: ::} !至少为了性能!

现在,这些天我正在使用 Laravel,它很棒;它提供(除了 Blade 和任何其他 3rd 方引擎)一个使用 ob_start/include/ob_get_clean 和 eval 的普通 PHP 模板系统。我很高兴知道我可以避免学习在 HTML 中编写 PHP 的新语法。

这是我的建议;我们使用闭包而不是使用带有包含的 ob_* 函数怎么样?这是我整理的一个简单的类,只是为了说明一点

class Templates{

static public $templates    = array();

static public function create($name, $code){
    self::$templates[$name] = $code;
}

static public function run($name, $data){
    if(!isset(self::$templates[$name]) || !is_callable(self::$templates[$name])) return false;
    return call_user_func(self::$templates[$name], $data);
}

}

以下是如何使用它:

Templates::create('test', function($data){
    return 'Hi '.$data['name'].' ! ';
});

for($i =0; $i < 10; $i++){
    print Templates::run('test', array('name' => 'Jhon'));
}

我认为这种方式要好得多,因为我不需要做任何输出缓冲或使用 eval。而为了在这里“分离关注点”,我们可以将 Templates::create 代码放在一个单独的文件中以保持干净,实际上这样可以变得更加简单和优雅;我们可以用另一种方法来加载模板文件:

static public function load($name){
    self::create($name, include($name.'.php'));
}

模板文件的内容会很简单:

return function($data){
    return 'Hi '.$data['name'].' ! ';
};

你觉得这怎么样 ?使用闭包的方法或性能是否有任何问题?

4

1 回答 1

1

除了将所有闭包函数放入数组之外,我认为没有任何问题,这可能意味着函数在做基本相同的事情。

我的意思是:

在您的示例中,您的函数仅接受 1 个参数。所以,不要把你创建的所有函数都弄得accept the same set of parameters一团糟return the same type of data

然而,当分开声明时,函数可能应该做一些不同和独特的事情。

为什么这样的解决方案是合适的:当使用一些引擎时,可能已经声明了很多不同的函数。为了解决冲突,可以将它们“隐藏”在数组中。

此外,有些人甚至说匿名函数在性能方面通常会更好。但我们必须先测试一下:要调用一个函数,你:

  1. 调用静态函数run
  2. 检查函数是否存在
  3. 检查函数的可调用性
  4. 然后使用call_user_funcwhich 返回函数的返回值。所以,3倍回报。

Update

我给你的代码推荐:

仅在创建函数时进行所有可能的检查。这将大大提高性能。

static public function create($name, $code){
  if (!isset(self::$templates[$name])){
    if (is_callable($code)){
      self::$templates[$name] = $code ;
    } else {
      //func is not callable, Throw an exception.
    }
  } else {
    //function already exists. Throw an exception.
  }
}

这样您就可以将性能提高 2 倍:

static public function run($name, $data){
  if (isset(self::$templates[$name])){
    self::$templates[$name]($data); //Just make a straight call
  } else {
    //throw new Exception(0, "The func is not defined") ;
  }
}
于 2013-06-22T15:13:47.217 回答