Короткий вопрос: повлияло ли поведение $this
в области изменения с PHP 5.3.29 до 5.5.24? Я не мог найти какие-либо соответствующие изменения в PHP 5 Changelog.
Подробности:
В этот вопрос, Я думал, что у меня есть решение для моей проблемы (В 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, или я должен искать в другом месте причину сбоя на одном сервере, а не на другом?
Причина в том, что в этот момент вы изменили рамки. Я не уверен, что изменилось, но ваш код должен не работать, по крайней мере, как правила области видимости 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));
}));
Да, в 5.4 есть важное различие:
- Добавлено закрытие $ этой поддержки назад.
Значение в 5.3, $this
внутри анонимной функции ничего не упоминалось, окружающий контекст не сохранялся. 5.4 добавлена поддержка этого (назад), поэтому $this
внутри анонимной функции относится к $this
из окружающего контекста. Обходной путь раньше был:
$_this = $this;
function () use ($_this) {
$_this->foo();
};