Skip to content

Instantly share code, notes, and snippets.

@mnapoli
Last active March 15, 2016 22:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mnapoli/3744f4ea204eab70d527 to your computer and use it in GitHub Desktop.
Save mnapoli/3744f4ea204eab70d527 to your computer and use it in GitHub Desktop.
PHP-DI 6

PHP-DI 6 ideas

Main changes:

Rename a few helpers to actions:

  • factory() -> call()
  • object() -> create()

This is hopefully clearer on what will actually be done.

Same for object() methods:

  • ->constructor(...) -> ->parameters(...)
  • ->method(...) -> ->call(...)

object() is too magic (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

It will be much clearer (less suprises is always better), and we'll be able to add support for "explicit autowiring" where you only get autowiring when using autowire(), which I think is really good when you don't want too much magic.

Add a way to set parameters on call(): call(function (...) {...})->parameters(get('abc'), get('def')).

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?

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment