On this page
Caution
The documentation you are viewing is for an older version of this component.
Switch to the latest (v3) version.
Reference
Dependency Definitions
Definitions are what laminas-di uses to understand the structure of the code it is attempting to wire. This means that if you've written non-ambiguous, clear, and concise code, laminas-di has a very good chance of understanding how to wire things up without much added complexity.
DefinitionList
Definitions are introduced to the Laminas\Di\Di
object through a definition list
implemented as Laminas\Di\DefinitionList
(which extends SplDoublyLinkedList
).
Order is important. Definitions in the front of the list will be consulted on a
class before definitions at the end of the list.
Autoloading
Regardless of what kind of
DefinitionList
strategy you decide to use, it is important that your autoloaders are already setup and ready to use.
RuntimeDefinition
The default DefinitionList
instantiated by Laminas\Di\Di
when no other
DefinitionList is provided is Laminas\Di\Definition\RuntimeDefinition
. The
RuntimeDefinition
will respond to queries about classes by using PHP's
Reflection API. The RuntimeDefinition
uses any available information inside
methods — including their signature, the names of parameters, the
type-hints of the parameters, and the default values — to determine if
something is optional or required when making a call to that method. The more
explicit you can be in your method naming and method signatures, the more likely
Laminas\Di\Definition\RuntimeDefinition
will accurately understand the structure
of your code.
The constructor of RuntimeDefinition
looks like the following:
public function __construct(
IntrospectionStrategy $introspectionStrategy = null,
array $explicitClasses = null
) {
$this->introspectionStrategy = $introspectionStrategy ?: new IntrospectionStrategy();
if ($explicitClasses) {
$this->setExplicitClasses($explicitClasses);
}
}
The IntrospectionStrategy
object is an object that defines the rules by which
the RuntimeDefinition
will introspect information about your classes. Here are
the things it knows how to do:
-
Whether or not to use annotations (scanning and parsing annotations is expensive, and thus disabled by default).
-
Which method names to include in the introspection; this is a list of patterns. By default, it registers the pattern
/^set\[A-Z\]{1}\\w\*/
. -
Which interface names represent the interface injection pattern; this is a list of patterns. By default, the pattern
/\\w\*Aware\\w\*/
is registered.
The constructor for the IntrospectionStrategy
looks like this:
public function __construct(AnnotationManager $annotationManager = null)
{
$this->annotationManager = $annotationManager ?: $this->createDefaultAnnotationManager();
}
The AnnotationManager
is not required. If you wish to create a special
AnnotationManager
with your own annotations, and also wish to extend the
RuntimeDefinition
to look for those annotations, this is the place to do it.
The RuntimeDefinition
also can be used to look up either all classes
(implicitly, which is default), or explicitly look up for particular pre-defined
classes. This is useful when your strategy for inspecting one set of classes
might differ from those of another strategy for another set of classes. This can
be achieved by using the setExplicitClasses()
method or by passing a list of
classes as the second constructor argument of the RuntimeDefinition
.
CompilerDefinition
The CompilerDefinition
is similar in nature to the RuntimeDefinition
with
the exception that it can be seeded with more information for the purposes of
"compiling" a definition. Compiled definitions eliminate reflection calls and
annotation scannning, which can be a performance bottleneck in your production
applications.
For example, let's assume we want to create a script that will create definitions for some of our library code:
// in "package name" format
$components = [
'My_MovieApp',
'My_OtherClasses',
];
foreach ($components as $component) {
$diCompiler = new Laminas\Di\Definition\CompilerDefinition;
$diCompiler->addDirectory('/path/to/classes/' . str_replace('_', '/', $component));
$diCompiler->compile();
file_put_contents(
__DIR__ . '/../data/di/' . $component . '-definition.php',
'<?php return ' . var_export($diCompiler->toArrayDefinition()->toArray(), true) . ';'
);
}
The above creates a file for each "package", containing the full definition for the classes defined for each. To utilize this in an application, use the following:
protected function setupDi(Application $app)
{
$definitionList = new DefinitionList([
new Definition\ArrayDefinition(include __DIR__ . '/path/to/data/di/My_MovieApp-definition.php'),
new Definition\ArrayDefinition(include __DIR__ . '/path/to/data/di/My_OtherClasses-definition.php'),
$runtime = new Definition\RuntimeDefinition(),
]);
$di = new Di($definitionList, null, new Config($this->config->di));
$di->instanceManager()->addTypePreference('Laminas\Di\LocatorInterface', $di);
$app->setLocator($di);
}
The above code would more than likely go inside your application's bootstrap or
within a Module
class. This represents the simplest and most performant way
of configuring your DiC for usage.
ClassDefinition
The idea behind using a ClassDefinition
is two-fold. First, you may want to
override some information inside of a RuntimeDefinition
. Secondly, you might
want to simply define your complete class's definition with an xml, ini, or php
file describing the structure. This class definition can be fed in via
Configuration
or by directly instantiating and registering the Definition
with the DefinitionList
.