【问题标题】:Did the behavior of `$this` in a scope change from PHP 5.3.29 to 5.5.24?`$this` 在范围内的行为是否从 PHP 5.3.29 更改为 5.5.24?
【发布时间】:2015-11-11 12:35:32
【问题描述】:

小问题:$this 在范围内的行为是否从 PHP 5.3.29 更改为 5.5.24?我在PHP 5 Changelog 中找不到任何相关更改。

详情: 在this question 中,我认为我有一个解决问题的方法(在 PHPUnit 中,期望以数组为参数的方法调用)。这是我的解决方案

public function test_actionUpload_v10MasterdataFile()
{
    /*
     * Create a stub to disable the original constructor.
     * Exposing data and rendering are stubbed.
     * All other methods behave exactly the same as in the real Controller.
     */
    $sut = $this->getMockBuilder('MasterdataController')
                ->setMethods(array('exposeAndSaveDataLines', 'render'))
                ->disableOriginalConstructor()
                ->getMock();

    $sut->expects($this->once())
        ->method('exposeAndSaveDataLines')
        ->will($this->returnCallback(function($lines) {
            $expectedLines = include ($this->dataDir() . 'ExpectedLines.php');
            PHPUnit_Framework_Assert::assertTrue($this->similar_arrays($lines, $expectedLines));
        }));

    // Execute the test
    $sut->actionUpload();
}

它在我的本地环境(PHP 5.5.24,Zend Engine v2.5.0)上运行,但是当我将代码复制到我们的测试服务器(PHP 5.3.29,Zend Engine v2.3.0)时,这不起作用,由于这一行:

$expectedLines = include ($this->dataDir() . 'ExpectedLines.php');

错误是:

Using $this when not in object context

这可能是由于 PHP 版本,还是我应该在其他地方寻找它在一台服务器上失败但在另一台服务器上失败的原因?

【问题讨论】:

  • 你在闭包中使用$this,显然它不会从调用范围继承任何变量。

标签: php zend-framework phpunit this


【解决方案1】:

是的,5.4 中引入了一个重要的区别:

  • 添加了对 $this 的闭包支持。

意思是,在 5.3 中,匿名函数内部的 $this 没有引用任何内容,周围的上下文没有被保留。 5.4 增加了对 this (back) 的支持,所以匿名函数内的 $this 指的是来自周围上下文的 $this。之前的解决方法是:

$_this = $this;
function () use ($_this) {
    $_this->foo();
};

【讨论】:

    【解决方案2】:

    原因是您此时已更改范围。我也不确定发生了什么变化,但你的代码应该工作,至少 PHP 范围规则的定义方式是这样。以下是您解决此问题的代码:

    $sut->expects($this->once())
        ->method('exposeAndSaveDataLines')
        ->will($this->returnCallback(function($lines) {
            $expectedLines = include ($this->dataDir() . 'ExpectedLines.php');
            PHPUnit_Framework_Assert::assertTrue($this->similar_arrays($lines, $expectedLines));
        }));
    

    returnCallback 函数内部,从技术上讲,您仍然处于类的“内部”,但是您需要从外部范围导入 变量(PHP 中的这种行为与其他语言不同,例如不需要这个的Javascript)。它应该是这样工作的:

    $self = $this; // Not necessary after PHP 5.4 where you can just use($this)
    $sut->expects($this->once())
            ->method('exposeAndSaveDataLines')
            ->will($this->returnCallback(function($lines) use($self) {
                $expectedLines = include ($self->dataDir() . 'ExpectedLines.php');
                PHPUnit_Framework_Assert::assertTrue($self->similar_arrays($lines, $expectedLines));
            }));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 2016-08-16
      • 1970-01-01
      • 2011-05-11
      • 1970-01-01
      • 2021-11-08
      相关资源
      最近更新 更多