This repository has been archived by the owner on Jan 29, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
7 changed files
with
666 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Zend\\Di Configuration | ||
|
||
Most of the configuration for both the setup of Definitions as well as the setup of the Instance | ||
Manager can be attained by a configuration file. This file will produce an array (typically) and | ||
have a particular iterable structure. | ||
|
||
The top two keys are 'definition' and 'instance', each specifying values for respectively, | ||
definition setup and instance manager setup. | ||
|
||
The definition section expects the following information expressed as a PHP array: | ||
|
||
```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 | ||
) | ||
) | ||
|
||
) | ||
) | ||
) | ||
); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
# Zend\\Di Debugging & Complex Use Cases | ||
|
||
## Debugging a DiC | ||
|
||
It is possible to dump the information contained within both the Definition and InstanceManager for | ||
a Di instance. | ||
|
||
The easiest way is to do the following: | ||
|
||
```php | ||
Zend\Di\Display\Console::export($di); | ||
``` | ||
|
||
If you are using a RuntimeDefinition where upon you expect a particular definition to be resolve at | ||
the first-call, you can see that information to the console display to force it to read that class: | ||
|
||
```php | ||
Zend\Di\Display\Console::export($di, array('A\ClassIWantTo\GetTheDefinitionFor')); | ||
``` | ||
|
||
## Complex Use Cases | ||
|
||
### Interface Injection | ||
|
||
```php | ||
namespace Foo\Bar { | ||
class Baz implements BamAwareInterface | ||
{ | ||
public $bam; | ||
|
||
public function setBam(Bam $bam) | ||
{ | ||
$this->bam = $bam; | ||
} | ||
} | ||
class Bam | ||
{ | ||
} | ||
interface BamAwareInterface | ||
{ | ||
public function setBam(Bam $bam); | ||
} | ||
} | ||
|
||
namespace { | ||
include 'zf2bootstrap.php'; | ||
$di = new Zend\Di\Di; | ||
$baz = $di->get('Foo\Bar\Baz'); | ||
} | ||
``` | ||
|
||
### Setter Injection with Class Definition | ||
|
||
```php | ||
namespace Foo\Bar { | ||
class Baz | ||
{ | ||
public $bam; | ||
|
||
public function setBam(Bam $bam) | ||
{ | ||
$this->bam = $bam; | ||
} | ||
} | ||
class Bam { | ||
} | ||
} | ||
|
||
namespace { | ||
$di = new Zend\Di\Di; | ||
$di->configure(new Zend\Di\Config(array( | ||
'definition' => array( | ||
'class' => array( | ||
'Foo\Bar\Baz' => array( | ||
'setBam' => array('required' => true) | ||
) | ||
) | ||
) | ||
))); | ||
$baz = $di->get('Foo\Bar\Baz'); | ||
} | ||
``` | ||
|
||
### Multiple Injections To A Single Injection Point | ||
|
||
```php | ||
namespace Application { | ||
class Page | ||
{ | ||
public $blocks; | ||
|
||
public function addBlock(Block $block) | ||
{ | ||
$this->blocks[] = $block; | ||
} | ||
} | ||
interface Block | ||
{ | ||
} | ||
} | ||
|
||
namespace MyModule { | ||
class BlockOne implements \Application\Block {} | ||
class BlockTwo implements \Application\Block {} | ||
} | ||
|
||
namespace { | ||
include 'zf2bootstrap.php'; | ||
$di = new Zend\Di\Di; | ||
$di->configure(new Zend\Di\Config(array( | ||
'definition' => array( | ||
'class' => array( | ||
'Application\Page' => array( | ||
'addBlock' => array( | ||
'block' => array('type' => 'Application\Block', 'required' => true) | ||
) | ||
) | ||
) | ||
), | ||
'instance' => array( | ||
'Application\Page' => array( | ||
'injections' => array( | ||
'MyModule\BlockOne', | ||
'MyModule\BlockTwo' | ||
) | ||
) | ||
) | ||
))); | ||
$page = $di->get('Application\Page'); | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
# Zend\\Di Definition | ||
|
||
Definitions are the place where Zend\\Di attempts 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; | ||
Zend\\Di has a very good chance of understanding how to wire things up without much added | ||
complexity. | ||
|
||
## DefinitionList | ||
|
||
Definitions are introduced to the Zend\\Di\\Di object through a definition list implemented as | ||
Zend\\Di\\DefinitionList (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. | ||
|
||
> ## Note | ||
Regardless of what kind of Definition strategy you decide to use, it is important that your | ||
autoloaders are already setup and ready to use. | ||
|
||
## RuntimeDefinition | ||
|
||
The default DefinitionList instantiated by Zend\\Di\\Di, when no other DefinitionList is provided, | ||
has as Definition\\RuntimeDefinition baked-in. The RuntimeDefinition will respond to query's about | ||
classes by using Reflection. This Runtime definitions uses any available information inside methods: | ||
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 easier of a time | ||
Zend\\Di\\Definition\\RuntimeDefinition will have determining the structure of your code. | ||
|
||
This is what the constructor of a RuntimeDefinition looks like: | ||
|
||
```php | ||
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 determines the rules, or guidelines, for how the | ||
RuntimeDefinition will introspect information about your classes. Here are the things it knows how | ||
to do: | ||
|
||
- Whether or not to use Annotations (Annotations are expensive and off by default, read more about | ||
these in the Annotations section) | ||
- Which method names to include in the introspection, by default, the pattern /^set\[A-Z\]{1}\\w\*/ | ||
is registered by default, this is a list of patterns. | ||
- Which interface names represent the interface injection pattern. By default, the pattern | ||
/\\w\*Aware\\w\*/ is registered, this is a list of patterns. | ||
|
||
The constructor for the IntrospectionStrategy looks like this: | ||
|
||
```php | ||
public function __construct(AnnotationManager $annotationManager = null) | ||
{ | ||
$this->annotationManager = ($annotationManager) ?: $this->createDefaultAnnotationManager(); | ||
} | ||
``` | ||
|
||
This goes to say that an AnnotationManager is not required, but if you wish to create a special | ||
AnnotationManager with your own annotations, and also wish to extend the RuntimeDefinition to look | ||
for these special 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 a second argument to the constructor of the RuntimeDefinition. | ||
|
||
## CompilerDefinition | ||
|
||
The CompilerDefinition is very much similar in nature to the RuntimeDefinition with the exception | ||
that it can be seeded with more information for the purposes of "compiling" a definition. This is | ||
useful when you do not want to be making all those (sometimes expensive) calls to reflection and the | ||
annotation scanning system during the request of your application. By using the compiler, a | ||
definition can be created and written to disk to be used during a request, as opposed to the task of | ||
scanning the actual code. | ||
|
||
For example, let's assume we want to create a script that will create definitions for some of our | ||
library code: | ||
|
||
```php | ||
// in "package name" format | ||
$components = array( | ||
'My_MovieApp', | ||
'My_OtherClasses', | ||
); | ||
|
||
foreach ($components as $component) { | ||
$diCompiler = new Zend\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) . ';' | ||
); | ||
} | ||
``` | ||
|
||
This will create a couple of files that will return an array of the definition for that class. To | ||
utilize this in an application, the following code will suffice: | ||
|
||
```php | ||
protected function setupDi(Application $app) | ||
{ | ||
$definitionList = new DefinitionList(array( | ||
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('Zend\Di\LocatorInterface', $di); | ||
$app->setLocator($di); | ||
} | ||
``` | ||
|
||
The above code would more than likely go inside your application's or module's bootstrap file. 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. | ||
|
||
Todo - example |
Oops, something went wrong.