aphiria / aphiria

A simple, extensible REST API framework for PHP
https://www.aphiria.com
MIT License
139 stars 5 forks source link

Cannot use Opis to serialize the DI container if it contains bindings with closure properties #14

Closed davidbyoung closed 4 years ago

davidbyoung commented 4 years ago

If we have the following:

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.

davidbyoung commented 4 years ago

Closing this issue now that we no longer support closure command handlers nor closure route actions.