Skip to content

Instantly share code, notes, and snippets.

@mnapoli
Last active December 15, 2015 06:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mnapoli/5215260 to your computer and use it in GitHub Desktop.
Save mnapoli/5215260 to your computer and use it in GitHub Desktop.
PHP-DI alternative configuration options

Reflections on PHP-DI configuration.

Currently, the configuration is in PHP or annotations, PHP config has the following advantages:

  • PHP developpers know PHP
  • IDE autocompletion/error detection
  • Bean definition using closures

Disadvantages of PHP:

  • A bit more difficult to read than YAML

Problems with current configuration:

  • "entries" and "aliases" are separate. Maybe they can be joined?
  • Bean definition is too constraint: impossible to define extra attributes like "scope", "lazy", or injection points (see PHP-DI/PHP-DI#28)

Possibility:

  • More annotations to allow full configuration through annotations
  • Allow also full configuration through PHP config
  • Allow also full configuration through YAML config?
<?php
// Current
Container::addConfiguration(array(
"entries" => array(
"myBean" => function(Container $c) {
return new MyClass($c["foo"]);
},
),
"aliases" => array(
"My\Interface" => "My\Implementation",
),
));
// Current with short arrays (PHP 5.4)
Container::addConfiguration([
"entries" => [
"myBean" => function(Container $c) {
return new MyClass($c["foo"]);
},
],
"aliases" => [
"My\Interface" => "My\Implementation",
],
]);
// Alternative
$configuration = $container->getConfiguration();
$configuration->useReflection(true);
$configuration->useAnnotations(true);
$configuration->addYAMLDefinitions('config/di.yml');
$configuration->addArrayDefinitions($arrayDefinitions);
$configuration->addArrayDefinitionsFromFile('config/di.php');
$configuration->setCache(new Doctrine\Common\Cache\ArrayCache(), $degug);
// with
$arrayDefinitions = [
'db.host' => 'localhost',
'db.port' => 5000,
'My\Interface' => [
// This is an alias
'class' => 'My\Implementation',
'lazy' => true,
'scope' => Scope::SINGLETON(),
],
'My\Implementation' => [
'constructor' => [
'host' => 'db.host',
'port' => 'db.port',
],
'methods' => [
'setFoo1' => My\Foo1::class, // PHP 5.5
'setFoo2' => [
'foo2' => 'My\Foo2',
],
'setFoo3' => [
'foo3' => [
'name' => 'My\Foo2',
'lazy' => true,
],
],
'setFoo4' => ['My\Foo2', 'My\Foo4bis'],
],
'properties' => [
'bar' => 'My\Bar',
'baz' => [
'name' => 'My\Baz',
'lazy' => true,
],
],
],
'myNamedInstance' => [
'function' => function(Container $c) {
return new MyClass($c['db.host']);
},
],
];
db.host: localhost
db.port: 5000
My\Interface:
# This is an alias
class: My\Implementation
lazy: true
scope: singleton
My\Implementation:
constructor:
host: db.host
port: db.port
methods:
setFoo1: My\Foo1
setFoo2:
foo2: My\Foo2
setFoo3:
foo3:
name: My\Foo3
lazy: true
setFoo4: [My\Foo4, My\Foo4bis]
properties:
bar: My\Bar
baz:
name: My\Baz
lazy: true
myNamedInstance:
class: MyClass
<h1>Pimple</h1>
<?php
$container['cookie_name'] = 'SESSION_ID';
$container['session_storage'] = function ($c) {
return new $c['session_storage_class']($c['cookie_name']);
};
?>
<h1>Symfony</h1>
YAML:
parameters:
# ...
mailer.transport: sendmail
services:
mailer:
class: Mailer
arguments: [%mailer.transport%]
newsletter_manager:
class: NewsletterManager
calls:
- [ setMailer, [ @mailer ] ]
PHP:
<?php
$container->setParameter('mailer.transport', 'sendmail');
$container
->register('mailer', 'Mailer')
->addArgument('%mailer.transport%');
$container
->register('newsletter_manager', 'NewsletterManager')
->addMethodCall('setMailer', array(new Reference('mailer')));
?>
<h1>Zend Framework</h1>
<?php
$config = array(
'definition' => array(
'compiler' => array(/* @todo compiler information */),
'runtime' => array(/* @todo runtime information */),
'class' => array(
'instantiator' => '', // the name of the instantiator, by default this is __construct
'supertypes' => array(), // an array of supertypes the class implements
'methods' => array(
'setSomeParameter' => array( // a method name
'parameterName' => array(
'name', // string parameter name
'type', // type or null
'is-required' // bool
)
)
)
)
)
);
?>
<h1>Aura.DI</h1>
<?php
$di->set('database', function() use ($di) {
return $di->newInstance('Example\Package\Database', [
'hostname' => 'localhost',
'username' => 'user',
'password' => 'passwd',
]);
});
$di->params['Example\Package\Database'] = [
'hostname' => 'localhost',
'username' => 'user',
'password' => 'passwd',
];
$di->set('database', function() use ($di) {
return $di->newInstance('Example\Package\Database');
});
// default params for the model factory
$di->params['Example\Package\ModelFactory'] = [
// a map of model names to model factories
'map' => [
'blog' => $di->newFactory('Example\Package\BlogModel'),
'wiki' => $di->newFactory('Example\Package\WikiModel'),
],
];
$di->set('database', $di->lazyNew('Example\Package\Database'));
// Setter injection
$di->setter['Example\Package\Foo']['setDb'] = $di->lazyNew('Example\Package\Database', [
'hostname' => 'example.com',
]);
?>
<h1>Ding</h1>
beans: !!map
aDependencyBean:
class: DependencyBean
scope: singleton
aspectBean:
class: AspectBean
scope: singleton
parentBean:
abstract: true
properties: !!map
someProperty:
ref: aDependencyBean
aspects:
aspectA:
pointcuts:
pointcutA:
method: invoke
expression: ^get.*
type: method
ref: aspectBean
childBean:
parent: parentBean
class: MyBean
scope: singleton
properties: !!map
someOtherProperty:
value: blah
Or annotations
<h1>Orno DI</h1>
<?php
$container->register('session', 'Session')
->withArguments([new Storage, 'my_session_key']);
$container->register('session', 'Session')
->withMethodCall('setStorage', [new Storage])
->withMethodCall('setSessionKey', ['my_session_key']);
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment