Я использую PHPUnit, чтобы сделать макет для тестирования.
class Item extends Object { protected static $_cache; }
Я довольно уверен, что насмехается над чем-то вроде этого (пожалуйста, поправьте меня, если я ошибаюсь):
class Mock_Item_randomstring extends Item { }
Когда кеш моего Item
заполняется, он проверяет, что передаваемый объект является экземпляром Item
. Поскольку макет явно не определяет $_cache
, он не проверяет тип экземпляра.
PHP вообще не документирует функции отражения. Есть ли способ установить статическую переменную после факта, чтобы класс стал
class Mock_Item_randomstring extends Item { protected static $_cache; }
РЕДАКТИРОВАТЬ
Я играл с методами отражения и сталкивался с различными проблемами. Вот что я смутил:
$mock = $this->getMock( 'Item', array( '_func' ), array( $argument1, $argument2 )); $mock = new ReflectionClass($mock); $mock->staticExpects( $this->exactly(2) )->method( '_func' );
Я был в предположении, что отражения копируют весь класс. Я получаю эту ошибку: Call to undefined method ReflectionClass::staticExpects()
Я склонен использовать несколько неприятный трюк для статических переменных класса в подклассах:
class A { protected static $cache; public static function getCache() { return static::$cache; } public static function setCache($val) { static::$cache = & $val; // note the '&' } } class B extends A {} A::setCache('A'); B::setCache('B'); A::getCache(); // 'A' B::getCache(); // 'B'
Конечно, лучше избегать статических переменных. Используйте выделенный объект кеша и вводите его при создании экземпляра класса.
Вам не обязательно. \Closure::bind
позволяет читать и назначать частные и защищенные статические свойства. См. Примерный код на http://www.php.net/manual/en/closure.bind.php