在过去的几个小时里,我一直在谷歌上搜索,试图弄清楚如何做到这一点。我只是想清楚我的问题不是 这个问题或那个问题,因为如果设置了变量,我并没有尝试检查脚本内部。我正在尝试在它之外进行检查,以查看它们是否在被解释之前被设置/传递给包含的文件,或者至少被有意义地解释到引发错误的地步。让我解释。
一点背景
我正在为我工作的公司创建一个供内部使用的实用程序包。我选择了以下两种方式之一来渲染模板:包含它们或输出渲染的字符串。
public function render($context = array()) {
do_action(self::TAG_CLASS_NAME.'_render_view', $this, $context);
if ( empty( $this->html ) ) {
ob_start();
$this->checkContext($context);
extract( $context );
require_once $this->getFullPath();
$renderedView = ob_get_contents();
ob_end_clean();
$this->html = $renderedView;
return $renderedView;
} else {
return $this->html;
}
}
public function includeView($context = array()) {
do_action(self::TAG_CLASS_NAME.'_include_view', $this, $context);
extract( $context );
include $this->getFullPath();
}
问题
在render
方法内部,我开始了一些输出缓冲。这样我就可以让解释器评估代码并将 HTML 输出为字符串(没有受到eval()
打击。在我的单元测试中,我体验了如果我遗漏了context
模板本身内部的 a 会发生什么。例如:如果我有一个context
看起来像这样的数组:
$context = array(
'message' => 'Morning'
);
以及一个如下所示的关联模板:
<?php echo "Hello ".$name."! Good ".$message; ?>
或这个
<p>Hello <?php echo $name; ?>! Good <?php echo $message; ?></p>
不管它的格式如何,只要context
正确地将变量传递给它。无论如何,省略$name
incontext
将导致"Undefined variable: $name"
E_NOTICE 消息。这是有道理的。您如何在创建通知之前“捕获”该未定义变量?
我曾尝试使用:
$rh = fopen($this->getFullPath(), 'r');
$contents = fread($rh, filesize($this->getFullPath()));
fclose($rh);
其中$contents
输出:
"<?php echo sprintf("Hello %s, Good %s.", $name, $greeting); ?>"
下一个合乎逻辑的步骤(无论如何对我来说,因此是问题)是提取该字符串中的变量。所以我简单地开始创建一个正则表达式来匹配那个字符串并捕获变量,但最终还是在这里,因为我觉得我在重复工作。我的意思是,PHP 解释器已经有效地做到了这一点,所以必须有一种方法来利用内置功能。也许?
说了这么多,我想做一些类似于这个伪代码的事情:
protected function checkContext($context) {
require $filename;
$availVars = get_defined_vars()
if ( $availVars !== $context ) {
setUnDefinedVar = null
}
}
话虽如此,这甚至可能不是正确的方法,但什么是正确的?在包含文件时,我是否让解释器在未定义的变量上失败?如果我让它失败,我是否会将自己暴露在任何安全漏洞中?注意:我没有通过$_GET
或设置模板中的任何变量$_POST
。
非常感谢任何答案。提前谢谢你。