Usually, you will not want arguments or values resolved at the time you specify them. For example, you may want a specify a new object instance as a constructor argument, but of course you don't want to instantiate that object at the moment of configuration. Instead, you probably want to instantiate it only at the moment of construction.
The Definitions class provides methods to allow for late resolution of arguments via Lazy instances. These Lazy arguments are resolved only as the Container reads from the Definitions.
env(string $varname[, string $vartype = null]) : Lazy\Env
Resolves to the value of the $varname
environment variable.
$def->{Foo::CLASS}
->argument(
'bar',
$def->env('BAR') // getenv('BAR')
);
You may optionally specify a type to cast the value to:
$def->{Foo::CLASS}
->argument(
'bar',
$def->env('BAR', 'int') // (int) getenv('BAR')
);
csEnv(string $varname[, string $vartype = null]) : Lazy\CsEnv
Resolves to an array of comma-separated values from the $varname
environment
variable. This is useful when you have to read from a list of values via an
environment string; for example:
NOTIFY_EMAILS="foo@example.com,bar@example.net,baz@example.org"
$def->{Notifier::CLASS}
->argument(
'addresses',
$def->csEnv('NOTIFY_EMAILS') // str_getcsv(getenv('NOTIFY_EMAILS'))
);
You may optionally specify a type to cast all of the values to:
$def->{IdList::CLASS}
->argument(
'ids',
$def->csEnv('ID_LIST', 'int')
);
call(callable $callable) : Lazy\Call
Resolves to the result returned by a callable; the callable must have this signature ...
function (Container $container)
... and may specify the return type.
For example:
$def->{Foo::CLASS}
->argument(
'bar',
$def->call(
function (Container $container) {
$bar = $container->new(Bar::CLASS);
// do some work with $bar, then:
return $bar->getValue();
}
)
);
functionCall(string $function, ...$arguments) : Lazy\FunctionCall
Resolves to the return of a function call.
$def->{Foo::CLASS}
->argument(
'bar',
$def->functionCall('barfunc') // barfunc()
);
Any or all of the $arguments
themselves can be Lazy as well.
staticCall(string|Lazy $class, string $method, ...$arguments) : Lazy\StaticCall
Resolves to the return of a static method call.
$def->{Foo::CLASS}
->argument(
'bar',
$def->staticCall('Bar', 'func') // Bar::func()
);
Any or all of the $arguments
themselves can be Lazy as well.
get(string|Lazy $id) : Lazy\Get
Resolves to an identified definition returned by Container::get()
.
$def->{Foo::CLASS}
->argument(
'bar',
$def->get(Bar::CLASS) // $container->get(Bar::CLASS)
);
getCall(string|Lazy $id, string $method, ...$arguments) : Lazy\GetCall
Resolves to a method call on an object returned by Container::get()
.
$def->{Foo::CLASS}
->method(
'setBarVal',
$def->getCall(Bar::CLASS, 'getValue') // $container->get(Bar::CLASS)->getValue()
);
Any or all of the $arguments
themselves can be Lazy as well.
new(string|Lazy $id) : Lazy\NewInstance
Resolves to an identified definition returned by Container::new()
.
$def->{Foo::CLASS}
->argument(
'bar',
$def->new(Bar::CLASS) // $container->new(Bar::CLASS)
);
newCall(string|Lazy $id, string $method, ...$arguments) : Lazy\NewCall
Resolves to a method call on an object returned by Container::new()
.
$def->{Foo::CLASS}
->method(
'setBarVal',
$def->newCall(Bar::CLASS, 'getValue') // $container->new(Bar::CLASS)->getValue()
);
Any or all of the $arguments
themselves can be Lazy as well.
callableGet(string|Lazy $id) : Lazy\CallableGet
callableNew(string|Lazy $id) : Lazy\CallableNew
These resolve to a closure around Container::get()
or Container::new()
.
Useful for providing factories to other containers or locators.
$def->{Foo::CLASS}
->argument(
'bar',
$def->callableGet(Bar::CLASS);
);
// function () use ($container) { return $container->get(Bar::CLASS); }
include(string|Lazy $file) : Lazy\IncludeFile
Resolves to the result returned by including a file; failure to find the file will not terminate execution.
$def->{Foo::CLASS}
->method(
'setBar',
$def->include('bar.php') // include 'bar.php'
);
require(string|Lazy $file) : Lazy\RequireFile
Resolves to the result returned by requiring a file; failure to find the file will terminate execution.
$def->{Foo::CLASS}
->method(
'setBar',
$def->require('bar.php') // require 'bar.php'
);
array(array $values) : Lazy\ArrayValues
Resolves to an array, where each element has itself been lazy-resolved.
Each element in the array will be inspected for Lazy resolution. This is a recursive inspection; if an array element is an array, that sub-array will also be lazy-resolved. You can mix Lazy and non-Lazy elements together in the array; the non-Lazy elements will be left as-is.
$def->{Foo::CLASS}
->argument('list', $def->array([
$def->env('BAR'), // getenv('BAR')
'BAZ',
$def->env('DIB'), // getenv('DIB')
])
The ArrayValues object implements ArrayAccess, Countable, and IteratorAggregate, so in many cases you can work with it as if it is an array:
$def->listing = $def->array([
'bar' => $def->env('BAR')
]);
$def->listing['baz'] = 'BAZ',
$def->listing['dib'] = $def->env('DIB');
$count = count($def->listing); // 3
unset($def->listing['baz']);
foreach ($def->listing as $key => $value) {
// ...
}
Finally, to merge any iterable
into an existing ArrayValues object, use its
merge()
method:
$def->listing = $def->array([
'foo',
'bar',
'baz' => 'dib',
]);
$def->listing->merge([
'zim',
'gir',
'irk' => 'doom',
]);
/*
$def->listing will now resolve to ...
[
'foo',
'bar',
'baz' => 'dib',
'zim',
'gir',
'irk' => 'doom',
]
*/
The merge()
method behaves just like array_merge().
Each definition itself is Lazy and will resolve to a new instance of the specified class as defined.
$def->{Foo::CLASS}
->argument(
'zim',
$def->newDefinition(Zim::CLASS) // new Zim()
);
Note that this is different from resolving via the Container as per new()
.
With a standalone definition, you can specify the arguments, modifiers,
factory, etc. separately from whatever the "default" definition is in
the Container.