scope — определение, является ли замыкание статическим в переполнении стека.

Закрытие, определенное в PHP, также может нести static модификатор.

$f = function () { };

$g = static function () { };

Статическое закрытие не может быть связано через Closure::bind или же Closure::bindTo, и выдаст предупреждение.

$g = Closure::bind(static function () { }, new stdClass());

// Warning: Cannot bind an instance to a static closure in ...

Это также относится и к замыканиям, созданным путем отражения статического метода с ReflectionMethod::getClosure.

class MyClass
{
public static function myStaticMethod() { }
}

// reflect MyClass::myStaticMethod,  create an unbound closure, and try to bind it
$f = (new ReflectionMethod(MyClass::class, 'myStaticMethod'))
->getClosure()
->bindTo(new stdClass());

// Warning: Cannot bind an instance to a static closure in ...

Хотя это раздражает, это приемлемо; однако, как можно проверить между статическим и нестатическим замыканием?

ReflectionMethod::isStatic казалось так может быть работать, но разумно не так Closure::__invoke это уровень экземпляра, а не статический.

$f = static function () { };

// reflect Closure::__invoke because I think I'm tricky
$r = new ReflectionMethod($f, '__invoke');

// and it's not static anyway
var_dump($r->isStatic()); // bool(false)

Далее проверка ReflectionMethod::getClosureThis обычно может работать, так как статический метод должен быть свободным, однако это не распространяется на замыкания, определенные вне метода экземпляра, или на угловой пример методов экземпляра, которые были несвязанный.

class MyClass
{
public function myInstanceMethod() { }
}

$o = new MyClass();

// reflect MyClass::myInstanceMethod, create a bound closure, and then unbind it
$f = (new ReflectionMethod($o, 'myInstanceMethod'))
->getClosure($o)
->bindTo(null);

// then reflect the closure
$r = new ReflectionFunction($f);

// and see it's bound to nothing, as would be the case of a static closure
var_dump($r->getClosureThis()); // NULL

Итак, чтобы переформулировать, как определить, является ли замыкание статическим (или, более конкретно, связываемый) или нет?

Это действительно кажется, что мы должны иметь ReflectionFunctionAbstract::isBindable, или это ReflectionMethod::isStatic быть перемещен в ReflectionFunctionAbstract,

6

Решение

Если привязка работает, у Closure будет $ this, привязанный к нему. Так что, просто свяжите это и затем проверьте на $ this. Если он нулевой, то это статическое замыкание.

function isBindable(\Closure $closure) {
return (new ReflectionFunction(@\Closure::bind($closure, new stdClass)))->getClosureThis() != null;
}
5

Другие решения

Это кажется невозможным сейчас.
Вы можете найти некоторые дебаты здесь: https://bugs.php.net/bug.php?id=64761
Единственный реальный обходной путь, который я использую для себя сейчас, это добавление ->isBindable свойство вручную.

Вот код, который я нашел здесь https://github.com/atoum/atoum/blob/master/classes/test/adapter/invoker.php
Может быть, даст вам несколько идей

protected static function isBindable(\closure $closure)
{
$isBindable = (version_compare(PHP_VERSION, '5.4.0') >= 0);
if ($isBindable === true)
{
$reflectedClosure = new \reflectionFunction($closure);
$isBindable = ($reflectedClosure->getClosureThis() !== null || $reflectedClosure->getClosureScopeClass() === null);
}
return $isBindable;
}
2

По вопросам рекламы [email protected]