class Foo
{
public \Closure $closure;
}
$container = new Container();
$foo = new Foo();
$foo->closure = fn () => void;
$container->bindInstance(Foo::class, $foo);
We cannot use Opis to serialize the container. We will get an error similar to the following:
[2020-01-18T15:58:25.225751+00:00] app.ERROR: Aphiria\Exceptions\FatalThrowableError: Type error: Typed property Foo::$closure must be an instance of Closure, Opis\Closure\SerializableClosure used in C:\Users\dyoung\PhpstormProjects\aphiria.com\vendor\opis\closure\src\SerializableClosure.php:428 Stack trace: #0 [internal function]: Aphiria\Exceptions\GlobalExceptionHandler->handleException(Object(TypeError)) #1 {main} [] []
This originally popped up because we added support for default exception responses. When running a console command that uses annotations, we create command bindings. However, the command handler factory uses $this (instance of AnnotationCommandRegistrant), which composes ICommandHandlerResolver, which, in this case is an instance of ContainerCommandHandlerResolver, which composes Container. When we go to serialize the command registry, Opis recursively attempts to wrap any Closure properties, which eventually gets to the default exception response factory that's composed in ExceptionResponseFactoryRegistry, which is bound to the container.
A simple, but not preferable, solution, is to just not use Closure typehints. However, this would be off-putting to userland.
If we have the following:
We cannot use Opis to serialize the container. We will get an error similar to the following:
This originally popped up because we added support for default exception responses. When running a console command that uses annotations, we create command bindings. However, the command handler factory uses
$this
(instance ofAnnotationCommandRegistrant
), which composesICommandHandlerResolver
, which, in this case is an instance ofContainerCommandHandlerResolver
, which composesContainer
. When we go to serialize the command registry, Opis recursively attempts to wrap anyClosure
properties, which eventually gets to the default exception response factory that's composed inExceptionResponseFactoryRegistry
, which is bound to the container.A simple, but not preferable, solution, is to just not use
Closure
typehints. However, this would be off-putting to userland.