在PHP中检查动态模板时出错

时间:2012-12-28 08:01:37

标签: php

我正在尝试使用PHP构建CMS,并且在构建模板系统时遇到一些麻烦。我不想使用Smarty或Twig因为我不想依赖外部框架,直到我可以流利地编写自己的代码。这完全是为了加强我的学习(从我的角度来看)。

所以我一直在计划模板是如何工作的,但是在错误检查方面遇到了麻烦。

以下是其工作原理的基本概述。

(非常)简单的样本模板:

<html>
<p>{output $randomNumber}</p>{output $databaseDump}
<div>{output $databaseAndUsersPasswords}</div>
</html>

由我的解析器解析:

<html>
<p><?php echo $randomNumber?></p><?php echo $databaseDump?>
<div><?php echo $databaseAndUsersPasswords?></div>
</html>

然后我使用eval运行解析后的模板。

我的问题在于错误检查。如果设计师出错了,那么对错误的保护就很少。启用错误抑制后,页面的一部分将丢失其内容。我希望它是全有或全无。我想不出一个简单的解决方案,可以让我检查错误。

另外,你认为我可以使用正则表达式和str_replace来解析模板吗?我一直在阅读其他一些框架解决方案,但它看起来非常复杂,我无法找到解析系统的核心。

请批评我喜欢的技巧。我在这里学习。

2 个答案:

答案 0 :(得分:4)

如果你想要全部或全部,你可以简单地配置一个错误处理程序并让它抛出异常:

function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    if (error_reporting()) {
        // the @ operator wasn't used, throw it.
        throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
    }
}
set_error_handler("exception_error_handler");

在此之后,您可以在include()块内try { } catch生成的脚本并使用输出缓冲来防止任何不需要的输出:

try {
    ob_start(); // stop output

    include '/path/to/script';

    ob_end_flush(); // flush buffer and stop output buffering
} catch (ErrorException $e) {
    ob_end_clean(); // clear buffer and stop output buffering
}

另请参阅:ErrorException


关于编写自己的模板引擎,我使用此规则:

  

如果它看起来像PHP,请使用PHP!

与PHP本身一样,几乎类似于PHP的语法对于设计人员来说同样难以学习,但是确保模板不会破坏自己的解析器所花费的精力肯定是有形的。

如果你想要更好地融入设计师工作的东西,请查看这个名为PHPTAL的项目,该项目使用XHTML属性进行变量替换并声明循环块,宏等。


有关错误报告和记录的更多信息:Error logging, in a smooth way

答案 1 :(得分:1)

首先,不要使用eval(阅读警告),除非有必要并且您没有其他选择。另一件事是,对于模板系统来说,查看视图,转换为php然后包含(运行)它是过度的。

我会使用MVC pattern并让控制器加载视图并将必要的信息传递给它而不将其作为脚本处理。

示例:


基础控制器:

abstract class Controller {
    protected function Render($view, $data = array()) {
        $viewStr = file_get_contents(__PATH_TO_VIEW__.$view.'.html');

        $viewStr = preg_replace_callback('/\{(\w+)\}/',
                                        function ($matches) use ($data) {
                                            return isset($data[$matches[1]]) ?
                                                          $data[$matches[1]] : '';
                                        }, $viewStr);
        echo $viewStr;
    }
}

自定义控制器:

class MyController extends Controller {
    public function index() {
        $this->Render('myView', array('test' => 'some test string'));
    }
}

自定义视图(此示例中为myView.html):

<b>{test}</b>

输出应为:

  

一些测试字符串


如你所见,你正在使用字符串,你没有运行任何东西,所以现在你可以完全控制视图,设计师无法产生php错误。

P.S。您可以随意调整现有代码。 ;)