rdlowrey / auryn

IoC Dependency Injector
MIT License
723 stars 65 forks source link

Exception on instantiating descendant of \ArrayObject #129

Closed msjyoo closed 1 year ago

msjyoo commented 8 years ago

Hello,

I think I've found a bug when auryn attempts to instantiate an object which is a descendant of \ArrayObject.

Exception / Stack trace:

PHP Fatal error:  Uncaught exception 'InvalidArgumentException' with message 'Passed variable is not an array or object, using empty array instead' in /project/g/php-typechecker/vendor/rdlowrey/auryn/lib/Injector.php:400
Stack trace:
#0 [internal function]: ArrayObject->__construct(NULL)
#1 /project/g/php-typechecker/vendor/rdlowrey/auryn/lib/Injector.php(400): ReflectionClass->newInstanceArgs(Array)
#2 /project/g/php-typechecker/vendor/rdlowrey/auryn/lib/Injector.php(367): Auryn\Injector->provisionInstance('sekjun9878\\Func...', 'sekjun9878\\func...', Array)
#3 /project/g/php-typechecker/vendor/rdlowrey/auryn/lib/Injector.php(522): Auryn\Injector->make('sekjun9878\\Func...')
#4 /project/g/php-typechecker/vendor/rdlowrey/auryn/lib/Injector.php(459): Auryn\Injector->buildArgFromTypeHint(Object(ReflectionMethod), Object(ReflectionParameter))
#5 /h in /project/g/php-typechecker/vendor/rdlowrey/auryn/lib/Injector.php on line 400

Class signatures:

final class FunctionDirectory extends Directory
abstract class Directory extends \ArrayObject

Workaround:

//$functionDirectory = $injector->make(FunctionDirectory::class);
$functionDirectory = new FunctionDirectory;
$injector->share($functionDirectory);
kelunik commented 7 years ago

Could you share a full reproducible code snippet, please?

msjyoo commented 7 years ago
<?php

require_once(__DIR__."/vendor/autoload.php");

final class FunctionDirectory extends Directory_ {}
abstract class Directory_ extends \ArrayObject {}

$injector = new Auryn\Injector;

$functionDirectory = $injector->make(FunctionDirectory::class);
PHP Fatal error:  Uncaught TypeError: ArrayObject::__construct() expects parameter 3 to be a class name derived from Iterator, '' given in /home/sekjun9878/Documents/Development/Projects/test/vendor/rdlowrey/auryn/lib/Injector.php:406
Stack trace:
#0 [internal function]: ArrayObject->__construct(NULL, NULL, '')
#1 /home/sekjun9878/Documents/Development/Projects/test/vendor/rdlowrey/auryn/lib/Injector.php(406): ReflectionClass->newInstanceArgs(Array)
#2 /home/sekjun9878/Documents/Development/Projects/test/vendor/rdlowrey/auryn/lib/Injector.php(373): Auryn\Injector->provisionInstance('FunctionDirecto...', 'functiondirecto...', Array)
#3 /home/sekjun9878/Documents/Development/Projects/test/test.php(10): Auryn\Injector->make('FunctionDirecto...')
#4 {main}
  thrown in /home/sekjun9878/Documents/Development/Projects/test/vendor/rdlowrey/auryn/lib/Injector.php on line 406
kelunik commented 7 years ago

This happens due to PHP not providing reflection information, see https://3v4l.org/plOeU.

While we could fix this particular case by omitting all remaining optional parameters, I think this should be solved in PHP itself providing better reflection information. In the end, it will break once one specifies a last parameter somewhere with the parameters before also optional and without provided reflection information.

In this case null is fine for the first two parameters, but not for the last one. In other cases this might be different.

You can solve this by explicitly providing the exact same constructor in userland, e.g. in Directory_. Another solution is to just define those parameters using Injector::define.

Danack commented 1 year ago

A mere seven years later, fixed in 113f8c79f30d02c70862b526f2036ed6f753292b