0

在过去的几个小时里,我一直在谷歌上搜索,试图弄清楚如何做到这一点。我只是想清楚我的问题不是 这个问题那个问题,因为如果设置了变量,我并没有尝试检查脚本内部。我正在尝试在它之外进行检查,以查看它们是否在被解释之前被设置/传递给包含的文件,或者至少被有意义地解释到引发错误的地步。让我解释。

一点背景

我正在为我工​​作的公司创建一个供内部使用的实用程序包。我选择了以下两种方式之一来渲染模板:包含它们或输出渲染的字符串。

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正确地将变量传递给它。无论如何,省略$nameincontext将导致"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

非常感谢任何答案。提前谢谢你。

4

1 回答 1

0

我建议在你的班级中使用 getter 和 setter。可能有更好的解决方案,但这就是我的做法。由于您尝试访问全局范围内的变量,因此您可以将以下方法添加到调用包含文件的类中:

public function __get($variable)
{
    if (array_key_exists( $variable, $GLOBALS ))
        return $GLOBALS[$variable];

    return null;
}

所以现在在您包含的文件中,您可以使用

$this->{$variableName}

在您的具体情况下,它看起来像......

<?php echo "Hello ".$this->name."! Good ".$this->message; ?>

但是请注意,如果请求的变量是在调用类的范围内定义的,那么将返回该特定的成员变量。没有在全局范围内定义。

可以在此处找到有关此重载运算符的更好解释PHP Magic Methods

于 2017-03-28T18:31:23.607 回答