una tiene tag solo sintaxis que otra necesidad etiquetas etiqueta código codigo close cierre cerrar basica abrir php scope closures static-methods

tiene - php etiquetas html



Determinar si un cierre es estático en PHP (2)

Parece imposible ahora.
Puede encontrar algunos debates aquí: https://bugs.php.net/bug.php?id=64761
La única solución real que uso ahora es añadir ->isBindable propiedad ->isBindable manual.

Aquí hay un código que encontré aquí https://github.com/atoum/atoum/blob/master/classes/test/adapter/invoker.php
Tal vez le dará algunas ideas

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; }

Un cierre definido en PHP también puede llevar el modificador static .

$f = function () { }; $g = static function () { };

El cierre estático no puede vincularse mediante Closure::bind o Closure::bindTo , y emitirá una advertencia.

$g = Closure::bind(static function () { }, new stdClass()); // Warning: Cannot bind an instance to a static closure in ...

Este es también el caso de los cierres creados al reflejar un método estático con 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 ...

Aunque molesto, esto es aceptable; sin embargo, ¿cómo se debe probar entre un cierre estático y no estático?

ReflectionMethod::isStatic parecía que podría funcionar, pero con sensatez no es porque Closure::__invoke es a nivel de instancia, no estático.

$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)

Además, comprobar ReflectionMethod::getClosureThis generalmente puede funcionar, ya que un método estático debe ser independiente, sin embargo, eso no cubre los cierres definidos fuera de un método de instancia, o el caso de esquina de los métodos de instancia que han sido desatados .

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

Entonces, para replantear, ¿cómo se determina si un cierre es estático ( o más específicamente, vinculable ) o no?

Realmente parece que deberíamos tener un ReflectionFunctionAbstract::isBindable , o que ReflectionMethod::isStatic se mueva hasta ReflectionFunctionAbstract .


Si el enlace funciona, el Cierre tendrá $ a esto vinculado. Entonces, solo agréguela y luego revise por $ this. Si es nulo, bueno, entonces es un Cierre estático.

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