Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Zend\Di documentation initial commit

  • Loading branch information...
commit 59f94679b186e28e2503a04b6f0d1a9aefa4653b 1 parent e575edd
@ralphschindler ralphschindler authored
View
41 documentation/manual/en/manual.xml.in
@@ -798,6 +798,47 @@
<!--</xi:include>-->
<!--</chapter>-->
+ <chapter xml:id="zend.di">
+ <info><title>Zend\Di</title></info>
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Di-Introduction.xml" parse="xml">
+ <xi:fallback>
+ <xi:include href="../en/module_specs/Zend_Di-Introduction.xml" parse="xml"/>
+ </xi:fallback>
+ </xi:include>
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Di-Quickstart.xml" parse="xml">
+ <xi:fallback>
+ <xi:include href="../en/module_specs/Zend_Di-Quickstart.xml" parse="xml"/>
+ </xi:fallback>
+ </xi:include>
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Di-Definitions.xml" parse="xml">
+ <xi:fallback>
+ <xi:include href="../en/module_specs/Zend_Di-Definitions.xml" parse="xml"/>
+ </xi:fallback>
+ </xi:include>
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Di-InstanceManager.xml" parse="xml">
+ <xi:fallback>
+ <xi:include href="../en/module_specs/Zend_Di-InstanceManager.xml" parse="xml"/>
+ </xi:fallback>
+ </xi:include>
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Di-Configuration.xml" parse="xml">
+ <xi:fallback>
+ <xi:include href="../en/module_specs/Zend_Di-Configuration.xml" parse="xml"/>
+ </xi:fallback>
+ </xi:include>
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Di-Debugging-and-Complex-Use.xml" parse="xml">
+ <xi:fallback>
+ <xi:include href="../en/module_specs/Zend_Di-Debugging-and-Complex-Use.xml" parse="xml"/>
+ </xi:fallback>
+ </xi:include>
+
+ </chapter>
+
<!--<chapter xml:id="zend.dojo"><info><title>Zend_Dojo</title></info>-->
<!---->
<!--<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Dojo.xml" parse="xml">-->
View
112 documentation/manual/en/manual2.xml.in
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE book [
- <!-- Add translated specific definitions and snippets -->
- <!ENTITY % language-snippets SYSTEM "./ref/language-snippets.xml">
- %language-snippets;
-
- <!-- Fallback to English definitions and snippets (in case of missing translation) -->
- <!ENTITY % language-snippets.default SYSTEM "../en/ref/language-snippets.xml">
- %language-snippets.default;
-]>
-<book xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="manual"
- xml:lang="&lang;">
- <info>
- <title>&book.title;</title>
- <subtitle>&book.subtitle;</subtitle>
- <edition>&book.edition;</edition>
- <pubdate><?dbtimestamp?></pubdate>
- <copyright>
- <year>2005-<?dbtimestamp format="Y"?></year>
- <holder>
- Zend Technologies Inc.
- (<uri xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.zend.com">http://www.zend.com</uri>)
- </holder>
- </copyright>
- </info>
-
- <part xml:id="learning">
- <info><title>&part.learning.title;</title></info>
-
-
- <chapter xml:id="learning.di"><info><title>Learning Dependency Injection</title></info>
-
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="tutorials/quickstart-di.xml" parse="xml">
- <xi:fallback>
- <xi:include href="../en/tutorials/quickstart-di.xml" parse="xml"/>
- </xi:fallback>
- </xi:include>
- </chapter>
- </part>
-
- <part xml:id="reference">
- <info><title>&part.reference.title;</title></info>
-
- <chapter xml:id="zend.event-manager">
- <info><title>Zend\EventManager</title></info>
-
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_EventManager-EventManager.xml" parse="xml">
- <xi:fallback>
- <xi:include href="../en/module_specs/Zend_EventManager-EventManager.xml" parse="xml"/>
- </xi:fallback>
- </xi:include>
- </chapter>
-
- <chapter xml:id="zend.http"><info><title>Zend\Http</title></info>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Http.xml" parse="xml">
- <xi:fallback>
- <xi:include href="../en/module_specs/Zend_Http.xml" parse="xml"/>
- </xi:fallback>
- </xi:include>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Http_Request.xml" parse="xml">
- <xi:fallback>
- <xi:include href="../en/module_specs/Zend_Http_Request.xml" parse="xml"/>
- </xi:fallback>
- </xi:include>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Http_Response.xml" parse="xml">
- <xi:fallback>
- <xi:include href="../en/module_specs/Zend_Http_Response.xml" parse="xml"/>
- </xi:fallback>
- </xi:include>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Http_Headers.xml" parse="xml">
- <xi:fallback>
- <xi:include href="../en/module_specs/Zend_Http_Headers.xml" parse="xml"/>
- </xi:fallback>
- </xi:include>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Http_Client.xml" parse="xml">
- <xi:fallback>
- <xi:include href="../en/module_specs/Zend_Http_Client.xml" parse="xml"/>
- </xi:fallback>
- </xi:include>
- </chapter>
-
- <chapter xml:id="zend.loader"><info><title>Zend_Loader</title></info>
-
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Loader.xml" parse="xml">
- <xi:fallback>
- <xi:include href="../en/module_specs/Zend_Loader.xml" parse="xml"/>
- </xi:fallback>
- </xi:include>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Loader-Autoloader-Resource.xml" parse="xml">
- <xi:fallback>
- <xi:include href="../en/module_specs/Zend_Loader-Autoloader-Resource.xml" parse="xml"/>
- </xi:fallback>
- </xi:include>
- </chapter>
-
- <chapter xml:id="zend.uri"><info><title>Zend_Uri</title></info>
-
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Uri.xml" parse="xml">
- <xi:fallback>
- <xi:include href="../en/module_specs/Zend_Uri.xml" parse="xml"/>
- </xi:fallback>
- </xi:include>
- </chapter>
-
- </part>
-
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="ref/copyrights.xml" parse="xml">
- <xi:fallback>
- <xi:include href="../en/ref/copyrights.xml" parse="xml"/>
- </xi:fallback>
- </xi:include>
-</book>
View
51 documentation/manual/en/module_specs/Zend_Di-Configuration.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Reviewed: no -->
+<section
+ xmlns="http://docbook.org/ns/docbook" version="5.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xml:id="zend.di.configuration">
+ <info><title>Zend\Di Configuration</title></info>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ The top two keys are 'definition' and 'instance', each
+ specifying values for respectively, definition setup and
+ instance manager setup.
+ </para>
+
+ <para>
+ The definition section expects the following information
+ expressed as a PHP array:
+ </para>
+
+ <programlisting language="php"><![CDATA[
+$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
+ )
+ )
+
+ )
+ )
+ )
+);
+]]></programlisting>
+
+</section>
View
156 documentation/manual/en/module_specs/Zend_Di-Debugging-and-Complex-Use.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Reviewed: no -->
+<section
+ xmlns="http://docbook.org/ns/docbook" version="5.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xml:id="zend.di.debugging-and-complex-use-cases">
+ <info><title>Zend\Di Debugging &amp; Complex Use Cases</title></info>
+
+ <section xml:id="zend.di.zend.di.debugging-and-complex-use-cases.debugging">
+ <info><title>Debugging a DiC</title></info>
+
+ <para>
+ It is possible to dump the information contained within both the
+ Definition and InstanceManager for a Di instance.
+ </para>
+
+ <para>
+ The easiest way is to do the following:
+ </para>
+
+
+ <programlisting language="php"><![CDATA[
+ Zend\Di\Display\Console::export($di);
+ ]]></programlisting>
+
+ <para>
+ 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:
+ </para>
+
+
+ <programlisting language="php"><![CDATA[
+ Zend\Di\Display\Console::export($di, array('A\ClassIWantTo\GetTheDefinitionFor'));
+ ]]></programlisting>
+
+ </section>
+
+ <section xml:id="zend.di.zend.di.debugging-and-complex-use-cases.complex-use-cases">
+ <info><title>Complex Use Cases</title></info>
+
+ <section xml:id="zend.di.zend.di.debugging-and-complex-use-cases.complex-use-cases.interface-injection">
+ <info><title>Interface Injection</title></info>
+
+ <programlisting language="php"><![CDATA[
+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');
+}
+]]></programlisting>
+
+
+ </section>
+
+
+ <section xml:id="zend.di.zend.di.debugging-and-complex-use-cases.complex-use-cases.setter-injection-with-class-definition">
+ <info><title>Setter Injection with Class Definition</title></info>
+
+ <programlisting language="php"><![CDATA[
+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\Configuration(array(
+ 'definition' => array(
+ 'class' => array(
+ 'Foo\Bar\Baz' => array(
+ 'setBam' => array('required' => true)
+ )
+ )
+ )
+ )));
+ $baz = $di->get('Foo\Bar\Baz');
+}
+]]></programlisting>
+
+ </section>
+
+
+ <section xml:id="zend.di.zend.di.debugging-and-complex-use-cases.complex-use-cases.multiple-injections">
+ <info><title>Multiple Injections To A Single Injection Point</title></info>
+
+
+ <programlisting language="php"><![CDATA[
+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\Configuration(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');
+}
+]]></programlisting>
+
+ </section>
+
+ </section>
+
+</section>
View
205 documentation/manual/en/module_specs/Zend_Di-Definitions.xml
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Reviewed: no -->
+<section
+ xmlns="http://docbook.org/ns/docbook" version="5.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xml:id="zend.di.definition">
+ <info><title>Zend\Di Definition</title></info>
+
+ <para>
+ 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.
+ </para>
+
+ <section xml:id="zend.di.definition.definitionlist">
+ <info><title>DefinitionList</title></info>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ 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.
+ </para>
+
+
+ </section>
+
+ <section xml:id="zend.di.definition.runtimedefinition">
+ <info><title>RuntimeDefinition</title></info>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ This is what the constructor of a RuntimeDefinition looks like:
+ </para>
+
+ <programlisting language="php"><![CDATA[
+public function __construct(IntrospectionStrategy $introspectionStrategy = null, array $explicitClasses = null)
+{
+ $this->introspectionStrategy = ($introspectionStrategy) ?: new IntrospectionStrategy();
+ if ($explicitClasses) {
+ $this->setExplicitClasses($explicitClasses);
+ }
+}
+]]></programlisting>
+
+ <para>
+ 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:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Whether or not to use Annotations (Annotations are expensive and off by default,
+ read more about these in the Annotations section)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ 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.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Which interface names represent the interface injection pattern. By default,
+ the pattern /\w*Aware\w*/ is registered, this is a list of patterns.
+ </para>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ The constructor for the IntrospectionStrategy looks like this:
+ </para>
+
+ <programlisting language="php"><![CDATA[
+public function __construct(AnnotationManager $annotationManager = null)
+{
+ $this->annotationManager = ($annotationManager) ?: $this->createDefaultAnnotationManager();
+}
+]]></programlisting>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ 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 setExplictClasses() method or by passing a list of classes as a second argument
+ to the constructor of the RuntimeDefinition.
+ </para>
+
+ </section>
+
+
+ <section xml:id="zend.di.definition.compilerdefinition">
+ <info><title>CompilerDefinition</title></info>
+
+ <para>
+ 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.
+ </para>
+
+
+ <para>
+ For example, let's assume we want to create a script that will create definitions
+ for some of our library code:
+ </para>
+
+
+ <programlisting language="php"><![CDATA[
+// 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) . ';'
+ );
+}
+]]></programlisting>
+
+ <para>
+ 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:
+ </para>
+
+ <programlisting language="php"><![CDATA[
+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 Configuration($this->config->di));
+ $di->instanceManager()->addTypePreference('Zend\Di\Locator', $di);
+ $app->setLocator($di);
+}
+]]></programlisting>
+
+ <para>
+ 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.
+ </para>
+
+
+ </section>
+
+
+ <section xml:id="zend.di.definition.classdefinition">
+ <info><title>ClassDefinition</title></info>
+
+ <para>
+ 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.
+ </para>
+
+ <para>Todo - example</para>
+
+ </section>
+
+</section>
View
235 documentation/manual/en/module_specs/Zend_Di-InstanceManager.xml
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Reviewed: no -->
+<section
+ xmlns="http://docbook.org/ns/docbook" version="5.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xml:id="zend.di.instancemanager">
+ <info><title>Zend\Di InstanceManager</title></info>
+
+ <para>
+ The InstanceManage is responsible for any runtime information associated
+ with the Zend\Di\Di DiC. This means that the information that goes into
+ the instance manager is specific to both how the particular consuming
+ Application's needs and even more specifically to the environment in
+ which the application is running.
+ </para>
+
+ <section xml:id="zend.di.instancemanager.parameters">
+ <info><title>Parameters</title></info>
+
+ <para>
+ Parameters are simply entry points for either dependencies or instance
+ configuration values. A class consist of a set of parameters, each
+ uniquely named. When writing your classes, you should attempt to
+ not use the same parameter name twice in the same class when you
+ expect that that parameters is used for either instance configuration
+ or an object dependency. This leads to an ambiguous parameter, and
+ is a situation best avoided.
+ </para>
+
+ <para>
+ Our movie finder example can be further used to explain these concepts:
+ </para>
+
+ <programlisting language="php"><![CDATA[
+namespace MyLibrary
+{
+ class DbAdapter
+ {
+ protected $username = null;
+ protected $password = null;
+ public function __construct($username, $password)
+ {
+ $this->username = $username;
+ $this->password = $password;
+ }
+ }
+}
+
+namespace MyMovieApp
+{
+ class MovieFinder
+ {
+ protected $dbAdapter = null;
+ public function __construct(\MyLibrary\DbAdapter $dbAdapter)
+ {
+ $this->dbAdapter = $dbAdapter;
+ }
+ }
+
+ class MovieLister
+ {
+ protected $movieFinder = null;
+ public function __construct(MovieFinder $movieFinder)
+ {
+ $this->movieFinder = $movieFinder;
+ }
+ }
+}
+]]></programlisting>
+
+ <para>
+ In the above example, the class DbAdapter has 2 parameters: username
+ and password; MovieFinder has one parameter: dbAdapter, and MovieLister
+ has one parameter: movieFinder. Any of these can be utilized for injection
+ of either dependencies or scalar values during instance configuration or
+ during call time.
+ </para>
+
+ <para>
+ When looking at the above code, since the dbAdapter parameter and the
+ movieFinder parameter are both type-hinted with concrete types, the DiC can
+ assume that it can fulfill these object tendencies by itself. On the other
+ hand, username and password do not have type-hints and are, more than likely,
+ scalar in nature. Since the DiC cannot reasonably know this information,
+ it must be provided to the instance manager in the form of parameters.
+ Not doing so will force $di->get('MyMovieApp\MovieLister') to throw an exception.
+ </para>
+
+ <para>
+ The following ways of using parameters are available:
+ </para>
+
+ <programlisting language="php"><![CDATA[
+// setting instance configuration into the instance manager
+$di->instanceManager()->setParameters('MyLibrary\DbAdapter', array(
+ 'username' => 'myusername',
+ 'password' => 'mypassword'
+));
+
+// forcing a particular dependency to be used by the instance manager
+$di->instanceManager()->setParameters('MyMovieApp\MovieFinder', array(
+ 'dbAdapter' => new MyLibrary\DbAdaper('myusername', 'mypassword')
+));
+
+// passing instance parameters at call time
+$movieLister = $di->get('MyMovieApp\MovieLister', array(
+ 'username' => $config->username,
+ 'password' => $config->password
+));
+
+// passing a specific instance at call time
+$movieLister = $di->get('MyMovieApp\MovieLister', array(
+ 'dbAdapter' => new MyLibrary\DbAdaper('myusername', 'mypassword')
+));
+]]></programlisting>
+
+ </section>
+
+
+ <section xml:id="zend.di.instancemanager.preferences">
+ <info><title>Preferences</title></info>
+
+ <para>
+ In some cases, you might be using interfaces as type hints as
+ opposed to concrete types. Lets assume the movie example
+ was modified in the following way:
+ </para>
+
+ <programlisting language="php"><![CDATA[
+namespace MyMovieApp
+{
+ interface MovieFinderInterface
+ {
+ // methods required for this type
+ }
+
+ class GenericMovieFinder
+ {
+ protected $dbAdapter = null;
+ public function __construct(\MyLibrary\DbAdapter $dbAdapter)
+ {
+ $this->dbAdapter = $dbAdapter;
+ }
+ }
+
+ class MovieLister
+ {
+ protected $movieFinder = null;
+ public function __construct(MovieFinderInterface $movieFinder)
+ {
+ $this->movieFinder = $movieFinder;
+ }
+ }
+}
+]]></programlisting>
+
+ <para>
+ What you'll notice above is that now the MovieLister type
+ minimally expects that the dependency injected implements the
+ MovieFinderInterface. This allows multiple implementations of
+ this base interface to be used as a dependency, if that is what
+ the consumer decides they want to do. As you can imagine, Zend\Di,
+ by itself would not be able to determine what kind of concrete
+ object to use fulfill this dependency, so this type of 'preference'
+ needs to be made known to the instance manager.
+ </para>
+
+ <para>
+ To give this information to the instance manager, see the following
+ code example:
+ </para>
+
+ <programlisting language="php"><![CDATA[
+$di->instanceManager()->addTypePreference('MyMovieApp\MovieFinderInterface', 'MyMovieApp\GenericMovieFinder');
+// assuming all instance config for username, password is setup
+$di->get('MyMovieApp\MovieLister');
+]]></programlisting>
+
+ </section>
+
+ <section xml:id="zend.di.instancemanager.aliases">
+ <info><title>Aliases</title></info>
+
+ <para>
+ In some situations, you'll find that you need to alias an instance.
+ There are two main reasons to do this. First, it creates a simpler, alternative
+ name to use when using the DiC, as opposed to using the full class name. Second,
+ you might find that you need to have the same object type in two separate contexts.
+ This means that when you alias a particular class, you can then attach a specific
+ instance configuration to that alias; as opposed to attaching that configuration
+ to the class name.
+ </para>
+
+ <para>
+ To demonstrate both of these points, we'll look at a use case where we'll have two
+ separate DbAdapters, one will be for read-only operations, the other will be
+ for read-write operations:
+ </para>
+
+ <para>
+ Note: Aliases can also have parameters registered at alias time
+ </para>
+
+ <programlisting language="php"><![CDATA[
+// assume the MovieLister example of code from the QuickStart
+
+$im = $di->instanceManager();
+
+// add alias for short naming
+$im->addAlias('movielister', 'MyMovieApp\MovieLister');
+
+// add aliases for specific instances
+$im->addAlias('dbadapter-readonly', 'MyLibrary\DbAdapter', array(
+ 'username' => $config->db->readAdapter->useranme,
+ 'password' => $config->db->readAdapter->password,
+));
+$im->addAlias('dbadapter-readwrite', 'MyLibrary\DbAdapter', array(
+ 'username' => $config->db->readWriteAdapter>useranme,
+ 'password' => $config->db->readWriteAdapter>password,
+));
+
+// set a default type to use, pointing to an alias
+$im->addTypePreference('MyLibrary\DbAdapter', 'dbadapter-readonly');
+
+$movieListerRead = $di->get('MyMovieApp\MovieLister');
+$movieListerReadWrite = $di->get('MyMovieApp\MovieLister', array('dbAdapter' => 'dbadapter-readwrite'));
+]]></programlisting>
+
+ </section>
+
+</section>
+
+
+
+
View
66 documentation/manual/en/module_specs/Zend_Di-Introduction.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Reviewed: no -->
+<section
+ xmlns="http://docbook.org/ns/docbook" version="5.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xml:id="zend.di.intro">
+ <info><title>Introduction to Zend\Di</title></info>
+
+ <section xml:id="zend.di.intro.di">
+ <info><title>Dependency Injection</title></info>
+ <para>
+ Dependency Injection (here-in called DI) is a concept that has
+ been talked about in numerous places over the web. Simply put,
+ we'll explain the act of injecting dependencies simply with
+ this below code:
+ </para>
+
+ <programlisting language="php"><![CDATA[
+$b = new MovieLister(new MovieFinder));
+]]></programlisting>
+
+ <para>
+ Above, MovieFinder is a dependency of MovieLister, and MovieFinder was injected into MovieLister. If you
+ are not familiar with the concept of DI, here are a couple of
+ great reads: <link xlink:href="http://weierophinney.net/matthew/archives/260-Dependency-Injection-An-analogy.html">Matthew
+ Weier O'Phinney's Analogy</link>,
+ <link xlink:href="http://ralphschindler.com/2011/05/18/learning-about-dependency-injection-and-php">Ralph
+ Schindler's Learning DI</link>, or
+ <link xlink:href="http://fabien.potencier.org/article/11/what-is-dependency-injection">Fabien
+ Potencier's Series</link> on DI.
+ </para>
+ </section>
+
+
+ <section xml:id="zend.di.intro.dic">
+ <info><title>Dependency Injection Containers</title></info>
+
+ <para>
+ When your code is written in such a way that all your dependencies
+ are injected into consuming objects, you might find that the simple
+ act of wiring an object has gotten more complex. When this becomes
+ the case, and you find that this wiring is creating more boilerplate
+ code, this makes for an excellent opportunity to utilize a
+ Dependency Injection Container.
+ </para>
+
+ <para>
+ In it's simplest form, a Dependency Injection Container (here-in
+ called a DiC for brevity), is an object that is capable of creating
+ objects on request and managing the "wiring", or the injection of
+ required dependencies, for those requested objects. Since the
+ patterns that developers employ in writing DI capable code vary,
+ DiC's are generally either in the form of smallish objects that
+ suit a very specific pattern, or larger DiC frameworks.
+ </para>
+
+ <para>
+ Zend\Di is a DiC framework. While for the simplest code there
+ is no configuration needed, and the use cases are quite simple; for
+ more complex code, Zend\Di is capable of being configured to wire
+ these complex use cases
+ </para>
+
+ </section>
+
+</section>
View
169 documentation/manual/en/module_specs/Zend_Di-Quickstart.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Reviewed: no -->
+<section
+ xmlns="http://docbook.org/ns/docbook" version="5.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xml:id="zend.di.quickstart">
+ <info><title>Zend\Di Quickstart</title></info>
+
+ <para>
+ This QuickStart is intended to get developers familiar with the concepts
+ of the Zend\Di DiC. Generally speaking, code is never as simple as it is
+ inside this example, so working knowledge of the other sections of the
+ manual is suggested.
+ </para>
+
+ <para>
+ Assume for a moment, you have the following code as part of your application
+ that you feel is a good candidate for being managed by a DiC, after all,
+ you are already injecting all your dependencies:
+ </para>
+
+
+ <programlisting language="php"><![CDATA[
+namespace MyLibrary
+{
+ class DbAdapter
+ {
+ protected $username = null;
+ protected $password = null;
+ public function __construct($username, $password)
+ {
+ $this->username = $username;
+ $this->password = $password;
+ }
+ }
+}
+
+namespace MyMovieApp
+{
+ class MovieFinder
+ {
+ protected $dbAdapter = null;
+ public function __construct(\MyLibrary\DbAdapter $dbAdapter)
+ {
+ $this->dbAdapter = $dbAdapter;
+ }
+ }
+
+ class MovieLister
+ {
+ protected $movieFinder = null;
+ public function __construct(MovieFinder $movieFinder)
+ {
+ $this->movieFinder = $movieFinder;
+ }
+ }
+}
+]]></programlisting>
+
+ <para>
+ With the above code, you find yourself writing the following to
+ wire and utilize this code:
+ </para>
+
+
+ <programlisting language="php"><![CDATA[
+// $config object is assumed
+
+$dbAdapter = new MyLibrary\DbAdapter($config->username, $config->password);
+$movieFinder = new MyMovieApp\MovieFinder($dbAdapter);
+$movieLister = new MyMovieApp\MovieLister($movieFinder);
+foreach ($movieLister as $movie) {
+ // iterate and display $movie
+}
+]]></programlisting>
+
+ <para>
+ If you are doing this above wiring in each controller or view that
+ wants to list movies, not only can this become repetitive and
+ boring to write, but also unmaintainable if for example you want to
+ swap out one of these dependencies on a wholesale scale.
+ </para>
+
+ <para>
+ Since this example of code already practices good dependency injection,
+ with constructor injection, it is a great candidate for using Zend\Di.
+ The usage is as simple as:
+ </para>
+
+
+ <programlisting language="php"><![CDATA[
+ // inside a bootstrap somewhere
+ $di = new Zend\Di\Di();
+ $di->instanceManager()->setParameters('MyLibrary\DbAdapter', array(
+ 'username' => $config->username,
+ 'password' => $config->password
+ ));
+
+ // inside each controller
+ $movieLister = $di->get('MyMovieApp\MovieLister');
+ foreach ($movieLister as $movie) {
+ // iterate and display $movie
+ }
+]]></programlisting>
+
+ <para>
+ In the above example, we are obtaining a default instance of
+ Zend\Di\Di. By 'default', we mean that Zend\Di\Di is constructed with
+ a DefinitionList seeded with a RuntimeDefinition (uses Reflection) and an
+ empty instance manager and no configuration.
+ Here is the Zend\Di\Di constructor:
+ </para>
+
+
+ <programlisting language="php"><![CDATA[
+ public function __construct(DefinitionList $definitions = null, InstanceManager $instanceManager = null, Configuration $config = null)
+ {
+ $this->definitions = ($definitions) ?: new DefinitionList(new Definition\RuntimeDefinition());
+ $this->instanceManager = ($instanceManager) ?: new InstanceManager();
+
+ if ($config) {
+ $this->configure($config);
+ }
+ }
+]]></programlisting>
+
+ <para>
+ This means that when $di->get() is called, it will be consulting the
+ RuntimeDefinition, which uses reflection to understand the structure of the code.
+ Once it knows the structure of the code, it can then know how the dependencies
+ fit together and how to go about wiring your objects for you.
+ Zend\Di\Definition\RuntimeDefinition will utilize the names of the parameters in the
+ methods as the class parameter names. This is how both username and password key
+ are mapped to the first and second parameter, respectively, of the constructor
+ consuming these named parameters.
+ </para>
+
+ <para>
+ If you were to want to pass in the username and password at call time, this is
+ achieved by passing them as the second argument of get():
+ </para>
+
+
+ <programlisting language="php"><![CDATA[
+ // inside each controller
+ $di = new Zend\Di\Di();
+ $movieLister = $di->get('MyMovieApp\MovieLister', array(
+ 'username' => $config->username,
+ 'password' => $config->password
+ ));
+ foreach ($movieLister as $movie) {
+ // iterate and display $movie
+ }
+]]></programlisting>
+
+ <para>
+ It is important to note that when using call time parameters, these parameter
+ names will be applied to any class that accepts a parameter of such name.
+ </para>
+
+ <para>
+ By calling $di->get(), this instance of MovieLister will be automatically shared.
+ This means subsequent calls to get() will return the same instance as previous
+ calls. If you wish to have completely new instances of MovieLister, you can
+ utilize $di->newInstance().
+
+ </para>
+
+</section>
View
8 working/build-manual2.php
@@ -28,9 +28,9 @@
}
$command = 'xsltproc --xinclude ' . $tempDir . '/phd/db4-upgrade.xsl '
- . $topDir . '/documentation/manual/en/manual2.xml.in > '
- . $tempDir . '/manual2.full.xml | tee -a '
- . $tempDir . '/manual2-err.txt';
+ . $topDir . '/documentation/manual/en/manual.xml.in > '
+ . $tempDir . '/manual.full.xml | tee -a '
+ . $tempDir . '/manual-err.txt';
colorPrint('Running: ' . $command, 'green');
nl();
system($command);
@@ -38,7 +38,7 @@
$command = $tempDir . '/phd/pear/phd -g \'phpdotnet\phd\Highlighter_GeSHi\' --xinclude -f zfpackage -d '
- . $tempDir . '/manual2.full.xml -o ' . $tempDir . '/manual-html';
+ . $tempDir . '/manual.full.xml -o ' . $tempDir . '/manual-html';
colorPrint('Running: ' . $command, 'green');
nl();
system($command);
Please sign in to comment.
Something went wrong with that request. Please try again.