Must haves:
- minimize BC breaks as much as possible (upgrading should be easy!) - when I say "rename" below, I mean we keep the old names to preserve BC but we deprecate them
- drop support for PHP 5.4 #361
- solve the
object()
helper that does too much and is too magic
What about PHP 5.5?
Main ideas:
Support PHP 7 and above only?
Remove scopes: #409
Rename a few helpers to actions:
factory()
-> call()
object()
-> create()
This is hopefully clearer on what will actually be done by the container.
Same for object()
methods (though I'm a little less convinced of the gain vs effort to migrate):
->constructor(...)
-> ->parameters(...)
->method(...)
-> ->call(...)
object()
is too magic (#294 extends autowiring and other definitions). We can split its behavior into:
create()
: create an object, doesn't extend autowiring or a previous definition
autowire()
: create an object using autowiring, also allows to set some parameters/method calls
extend()
: extend the previous definition to override constructor parameters/method calls #279 (it might even be removed altogether)
It will be much clearer (less surprises is always better), and we'll be able to add support for "explicit autowiring" where you only get autowiring when using autowire()
(optional of course), which I think is really good when you don't want too much magic.
Add a way to set parameters on call()
(#362, #239): call(function (...) {...})->parameters(get('abc'), get('def'))
.
Other ideas:
- migrate the cache to PSR-6? #376
Summary:
return [
'foo' => get('bar'),
'foo' => env('FOO'),
'foo' => string('{root}/test.txt'),
'foo' => create(MyClass::class),
MyClass::class => create(),
MyClass::class => create()
->with('param1', get('foo'))
->call('setLogger', get(Logger::class)),
'*Repository' => create('*DoctrineRepository'),
'foo' => autowire(MyClass::class),
MyClass::class => autowire()
->parameters(get('abc')),
MyClass::class => autowire()
->parameter('param1', get('abc')),
MyClass::class => autowire()
->call('setLogger', get(Logger::class)),
'bar' => extend('foo')
->parameter('param2', get('def')),
'bar' => extend()
->call('setLogger', get(Logger::class)),
'foo' => call(function () {
return 'bar';
}),
'foo' => call([Factory::class, 'method']),
'foo' => call([Factory::class, 'method'])
->parameters(get('abc')),
'foo' => call([Factory::class, 'method'])
->parameter('param1', get('abc')),
'api' => decorate(function ($previous, $c) {
return new CachedApi($previous);
}),
'log.handlers' => [
get(StreamHandler::class),
get(EmailHandler::class),
],
'log.handlers' => add([
get(SyslogHandler::class),
]),
];
Internal changes:
The configuration array could be turned into an AST and visitors could be applied (to turn it into a proper definition array). Then the resulting processed array of definitions could be cached.
Autowiring and annotation reader might not be "definition source" anymore (so much trouble from the beginning because of this).
That should solve problems of definitions nested in others (#297, #343), making caching easier and much more efficient (cache one array instead of each definition separately), maybe open the door for AST extensions, maybe open the door to compiling? It will also allow "validation passes" for dev environment (e.g. #243).
That config-to-AST part could be written as a separate package. It allows to write any configuration using PHP arrays, it could be useful. For example I needed exactly that for a framework and started a draft of such a thing (https://github.com/stratifyphp/framework/tree/master/src/Config).
Feedback and ideas are welcome!
enhancement