3

我正在编写简单的模板引擎和堆栈问题:$this即使在取消设置后也属于 eval 范围。

class foo
    {

    public function method()
        {
        $code = 'var_dump(isset($this));';
        unset($this);
        var_dump(isset($this)); // produce: boolean false
        eval($code); // produce: boolean true
        }

    }

$foo = new foo;
$foo ->method();

如何在不修改$code值的情况下避免这种情况?

4

4 回答 4

5

我建议创建unbound closure$this无法访问或可能被替换的地方。

笔记:

  1. Closures 自 PHP 5.3.0 起可用,正如@invisal 所提到的。
  2. Closure::bindTo自 PHP 5.4.0 起可用。
  3. Anonymous functions在 PHP 5.3.0 中不应继承$this自执行上下文。它从 PHP 5.4.0 开始启用。只需$evUl = $evUl->bindTo(null);从下面的 PHP 5.3.0 示例中删除,它就会按预期工作。

例子:

<?php
header('Content-Type: text/plain');

class foo {
    public function method() {
        $code = 'var_dump(isset($this));';

        $evUl = function()use($code){ eval($code); };
        $evUl = $evUl->bindTo(null);
        $evUl();
    }
}

$foo = new foo();
$foo->method();
?>

显示:

bool(false)
于 2013-06-13T02:29:01.407 回答
2

$this可以按照您的描述取消设置。

Zend_Framework 1.x 有一个实例,他们在Zend_Service_WindowsAzure_Storage_Batch课堂上这样做

请注意,这不会取消设置实例,只会取消对函数范围内的实例的引用。

尽管有文档,但这是自 php 5.1.6 以来观察到的行为。

我对为什么 this 不适用于 eval 的唯一猜测是它必须创建一个新的执行上下文,其中 $this 恢复到当前范围。此示例展示了该行为。

class A {
        public function test(){
                print "Before Unset\n";
                print_r($this);
                unset($this);
                print "After Unset\n";
                print_r($this);
                print "Evaled\n";
                eval("print_r(\$this);");
                print "After Eval\n";
                print_r($this);
        }
}
$a = new A();
$a->test();

其输出为:

Before Unset
A Object
(
)
After Unset
PHP Notice:  Undefined variable: this in /home/cgray/q.php on line 9
PHP Stack trace:
PHP   1. {main}() /home/cgray/q.php:0
PHP   2. A->test() /home/cgray/q.php:17
Evaled
A Object
(
)
After Eval
A Object
(
)

您可以避免此问题的一种方法是$this在评估的上下文中取消设置。

class foo
    {

    public function method()
        {
        $code = 'var_dump(isset($this));';
        unset($this);
        var_dump(isset($this)); 
        eval("unset(\$this);".$code); 
        }

$foo = new foo;
$foo->method();

更新

似乎include在函数范围内的文件也将恢复$this

于 2013-06-13T02:15:14.397 回答
1

$this是一个伪变量,它不能被取消设置。

http://php.net/manual/en/language.oop5.basic.php

于 2013-06-13T02:09:55.553 回答
1

似乎unset($this)只能在函数范围内工作。我已经通过测试确认了。

class foo
{
    public function method()
    {
        unset($this);
        var_dump(isset($this));
    }

    public function method2() {
        var_dump(isset($this));
    }
}

在函数内$code运行 eval 不在函数内运行method。经测试确认$code = 'echo __FUNCTION__;'

于 2013-06-13T02:23:56.240 回答