1 <?xml version="1.0" encoding="UTF-8"?>
3 <sect1 id="zend.application.theory-of-operation">
4 <title>Theory of Operation</title>
7 Getting an <acronym>MVC</acronym> application configured and ready to dispatch has
8 required an increasing amount of code as more features become
9 available: setting up the database, configuring your view and view
10 helpers, configuring your layouts, registering plugins, registering
11 action helpers, and more.
15 Additionally, you will often want to reuse the same code to
16 bootstrap your tests, a cronjob, or a service script. While it's
17 possible to simply include your bootstrap script, oftentimes there
18 are initializations that are environment specific – you may not need
19 the <acronym>MVC</acronym> for a cronjob, or just the DB layer for a service script.
23 <classname>Zend_Application</classname> aims to make this easier and to
24 promote reuse by encapsulating bootstrapping into <acronym>OOP</acronym> paradigms.
28 <classname>Zend_Application</classname> is broken into three realms:
34 <classname>Zend_Application</classname>: loads the <acronym>PHP</acronym>
35 environment, including include_paths and autoloading, and instantiates
36 the requested bootstrap class.
42 <classname>Zend_Application_Bootstrap</classname>: provides
43 interfaces for bootstrap classes.
44 <classname>Zend_Application_Bootstrap_Bootstrap</classname> provides common
45 functionality for most bootstrapping needs, including
46 dependency checking algorithms and the ability to load
47 bootstrap resources on demand.
53 <classname>Zend_Application_Resource</classname> provides an
54 interface for standard bootstrapping resources that can be
55 loaded on demand by a bootstrap instance, as well as several
56 default resource implementations.
62 Developers create a bootstrap class for their application, extending
63 <classname>Zend_Application_Bootstrap_Bootstrap</classname> or implementing (minimally)
64 <classname>Zend_Application_Bootstrap_Bootstrapper</classname>. The entry point
65 (e.g., <filename>public/index.php</filename>) will load
66 <classname>Zend_Application</classname>, and instantiate it by passing:
72 The current environment
78 Options for bootstrapping
84 The bootstrap options include the path to the file containing the
85 bootstrap class and optionally:
91 Any extra include_paths to set
97 Any additional autoloader namespaces to register
103 Any <filename>php.ini</filename> settings to initialize
109 The class name for the bootstrap class (if not "Bootstrap")
115 Resource prefix to path pairs to use
121 Any resources to use (by class name or short name)
127 Additional path to a configuration file to load
133 Additional configuration options
139 Options may be an array, a <classname>Zend_Config</classname> object, or the path
140 to a configuration file.
143 <sect2 id="zend.application.theory-of-operation.bootstrap">
144 <title>Bootstrapping</title>
147 <classname>Zend_Application</classname>'s second area of responsibility is
148 executing the application bootstrap. Bootstraps minimally need to
149 implement <classname>Zend_Application_Bootstrap_Bootstrapper</classname>,
150 which defines the following <acronym>API</acronym>:
153 <programlisting language="php"><![CDATA[
154 interface Zend_Application_Bootstrap_Bootstrapper
156 public function __construct($application);
157 public function setOptions(array $options);
158 public function getApplication();
159 public function getEnvironment();
160 public function getClassResources();
161 public function getClassResourceNames();
162 public function bootstrap($resource = null);
163 public function run();
168 This <acronym>API</acronym> allows the bootstrap to accept the environment and
169 configuration from the application object, report the resources its
170 responsible for bootstrapping, and then bootstrap and run the
175 You can implement this interface on your own, extend
176 <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>, or use
177 <classname>Zend_Application_Bootstrap_Bootstrap</classname>.
181 Besides this functionality, there are a number of other areas of
182 concern you should familiarize yourself with.
185 <sect3 id="zend.application.theory-of-operation.bootstrap.resource-methods">
186 <title>Resource Methods</title>
189 The <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
190 implementation provides a simple convention for defining class
191 resource methods. Any protected method beginning with a name
192 prefixed with <emphasis>_init</emphasis> will be considered a resource
197 To bootstrap a single resource method, use the
198 <methodname>bootstrap()</methodname> method, and pass it the name of the
199 resource. The name will be the method name minus the
200 <emphasis>_init</emphasis> prefix.
204 To bootstrap several resource methods, pass an array of names.
205 Too bootstrap all resource methods, pass nothing.
209 Take the following bootstrap class:
212 <programlisting language="php"><![CDATA[
213 class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
215 protected function _initFoo()
220 protected function _initBar()
225 protected function _initBaz()
233 To bootstrap just the <methodname>_initFoo()</methodname> method, do the
237 <programlisting language="php"><![CDATA[
238 $bootstrap->bootstrap('foo');
242 To bootstrap the <methodname>_initFoo()</methodname> and
243 <methodname>_initBar()</methodname> methods, do the following:
246 <programlisting language="php"><![CDATA[
247 $bootstrap->bootstrap(array('foo', 'bar'));
251 To bootstrap all resource methods, call <methodname>bootstrap()</methodname>
255 <programlisting language="php"><![CDATA[
256 $bootstrap->bootstrap();
260 <sect3 id="zend.application.theory-of-operation.bootstrap.resource-plugins">
261 <title>Bootstraps that use resource plugins</title>
264 To make your bootstraps more re-usable, we have provided the
265 ability to push your resources into resource plugin classes.
266 This allows you to mix and match resources simply via
267 configuration. We will cover <link
268 linkend="zend.application.theory-of-operation.resources">how
269 to create resources</link> later; in
270 this section we will show you how to utilize them only.
274 If your bootstrap should be capable of using resource plugins,
275 you will need to implement an additional interface,
276 <classname>Zend_Application_Bootstrap_ResourceBootstrapper</classname>.
277 This interface defines an <acronym>API</acronym> for locating, registering, and
278 loading resource plugins:
281 <programlisting language="php"><![CDATA[
282 interface Zend_Application_Bootstrap_ResourceBootstrapper
284 public function registerPluginResource($resource, $options = null);
285 public function unregisterPluginResource($resource);
286 public function hasPluginResource($resource);
287 public function getPluginResource($resource);
288 public function getPluginResources();
289 public function getPluginResourceNames();
290 public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader);
291 public function getPluginLoader();
296 Resource plugins basically provide the ability to create
297 resource intializers that can be re-used between applications.
298 This allows you to keep your actual bootstrap relatively clean,
299 and to introduce new resources without needing to touch your
304 <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname> (and
305 <classname>Zend_Application_Bootstrap_Bootstrap</classname> by extension)
306 implement this interface as well, allowing you to utilize
311 To utilize resource plugins, you must specify them in the
312 options passed to the application object and/or bootstrap. These
313 options may come from a configuration file, or be passed in
314 manually. Options will be of key to options pairs, with the key
315 representing the resource name. The resource name will be the
316 segment following the class prefix. For example, the resources
317 shipped with Zend Framework have the class prefix
318 "<classname>Zend_Application_Resource_</classname>"; anything following this would
319 be the name of the resource. As an example,
322 <programlisting language="php"><![CDATA[
323 $application = new Zend_Application(APPLICATION_ENV, array(
324 'resources' => array(
325 'FrontController' => array(
326 'controllerDirectory' => APPLICATION_PATH . '/controllers',
333 This indicates that the "FrontController" resource should be
334 used, with the options specified.
338 If you begin writing your own resource plugins, or utilize
339 third-party resource plugins, you will need to tell your
340 bootstrap where to look for them. Internally, the bootstrap
341 utilizes <classname>Zend_Loader_PluginLoader</classname>, so you will only
342 need to indicate the common class prefix an path pairs.
346 As an example, let's assume you have custom resource plugins in
347 <filename>APPLICATION_PATH/resources/</filename> and that they share the
348 common class prefix of <classname>My_Resource</classname>. You would then
349 pass that information to the application object as follows:
352 <programlisting language="php"><![CDATA[
353 $application = new Zend_Application(APPLICATION_ENV, array(
354 'pluginPaths' => array(
355 'My_Resource' => APPLICATION_PATH . '/resources/',
357 'resources' => array(
358 'FrontController' => array(
359 'controllerDirectory' => APPLICATION_PATH . '/controllers',
366 You would now be able to use resources from that directory.
370 Just like resource methods, you use the <methodname>bootstrap()</methodname>
371 method to execute resource plugins. Just like with resource
372 methods, you can specify either a single resource plugin,
373 multiple plugins (via an array), or all plugins. Additionally,
374 you can mix and match to execute resource methods as well.
377 <programlisting language="php"><![CDATA[
379 $bootstrap->bootstrap('FrontController');
382 $bootstrap->bootstrap(array('FrontController', 'Foo'));
384 // Execute all resource methods and plugins:
385 $bootstrap->bootstrap();
389 <sect3 id="zend.application.theory-of-operation.bootstrap.registry">
390 <title>Resource Registry</title>
393 Many, if not all, of your resource methods or plugins will
394 initialize objects, and in many cases, these objects will be
395 needed elsewhere in your application. How can you access them?
399 <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
400 provides a local registry for these objects. To store your
401 objects in them, you simply return them from your resources.
405 For maximum flexibility, this registry is referred to as a
406 "container" internally; its only requirements are that it is an
407 object. Resources are then registered as properties named after
408 the resource name. By default, an instance of
409 <classname>Zend_Registry</classname> is used, but you may also specify any
410 other object you wish. The methods <methodname>setContainer()</methodname>
411 and <methodname>getContainer()</methodname> may be used to manipulate the
412 container itself. <methodname>getResource($resource)</methodname> can be
413 used to fetch a given resource from the container, and
414 <methodname>hasResource($resource)</methodname> to check if the resource has
415 actually been registered.
419 As an example, consider a basic view resource:
422 <programlisting language="php"><![CDATA[
423 class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
425 protected function _initView()
427 $view = new Zend_View();
428 // more initialization...
436 You can then check for it and/or fetch it as follows:
439 <programlisting language="php"><![CDATA[
440 // Using the has/getResource() pair:
441 if ($bootstrap->hasResource('view')) {
442 $view = $bootstrap->getResource('view');
445 // Via the container:
446 $container = $bootstrap->getContainer();
447 if (isset($container->view)) {
448 $view = $container->view;
453 Please note that the registry and also the container is not global. This
454 means that you need access to the bootstrap in order to fetch
455 resources. <classname>Zend_Application_Bootstrap_Bootstrap</classname>
456 provides some convenience for this: during its
457 <methodname>run()</methodname> execution, it registers itself as the front
458 controller parameter "bootstrap", which allows you to fetch it
459 from the router, dispatcher, plugins, and action controllers.
463 As an example, if you wanted access to the view resource from
464 above within your action controller, you could do the following:
467 <programlisting language="php"><![CDATA[
468 class FooController extends Zend_Controller_Action
470 public function init()
472 $bootstrap = $this->getInvokeArg('bootstrap');
473 $view = $bootstrap->getResource('view');
480 <sect3 id="zend.application.theory-of-operation.bootstrap.dependency-tracking">
481 <title>Dependency Tracking</title>
484 In addition to executing resource methods and plugins, it's
485 necessary to ensure that these are executed once and once
486 only; these are meant to bootstrap an application, and
487 executing multiple times can lead to resource overhead.
491 At the same time, some resources may depend on other
492 resources being executed. To solve these two issues,
493 <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
494 provides a simple, effective mechanism for dependency
499 As noted previously, all resources -- whether methods or plugins
500 -- are bootstrapped by calling <methodname>bootstrap($resource)</methodname>,
501 where <varname>$resource</varname> is the name of a resource, an array
502 of resources, or, left empty, indicates all resources should be
507 If a resource depends on another resource, it should call
508 <methodname>bootstrap()</methodname> within its code to ensure that resource
509 has been executed. Subsequent calls to it will then be ignored.
513 In a resource method, such a call would look like this:
516 <programlisting language="php"><![CDATA[
517 class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
519 protected function _initRequest()
521 // Ensure the front controller is initialized
522 $this->bootstrap('FrontController');
524 // Retrieve the front controller from the bootstrap registry
525 $front = $this->getResource('FrontController');
527 $request = new Zend_Controller_Request_Http();
528 $request->setBaseUrl('/foo');
529 $front->setRequest($request);
531 // Ensure the request is stored in the bootstrap registry
539 <sect2 id="zend.application.theory-of-operation.resources">
540 <title>Resource Plugins</title>
544 linkend="zend.application.theory-of-operation.bootstrap.resource-plugins">As noted
545 previously</link>, a good way to create re-usable bootstrap resources and to
546 offload much of your coding to discrete classes is to utilize resource
547 plugins. While Zend Framework ships with a number of standard
548 resource plugins, the intention is that developers should write
549 their own to encapsulate their own initialization needs.
553 Resource plugins need only implement
554 <classname>Zend_Application_Resource_Resource</classname>, or, more simply
556 <classname>Zend_Application_Resource_ResourceAbstract</classname>. The basic
557 interface is simply this:
560 <programlisting language="php"><![CDATA[
561 interface Zend_Application_Resource_Resource
563 public function __construct($options = null);
564 public function setBootstrap(
565 Zend_Application_Bootstrap_Bootstrapper $bootstrap
567 public function getBootstrap();
568 public function setOptions(array $options);
569 public function getOptions();
570 public function init();
575 The interface defines simply that a resource plugin should accept options
576 to the constructor, have mechanisms for setting and retrieving
577 options, have mechanisms for setting and retrieving the bootstrap
578 object, and an initialization method.
582 As an example, let's assume you have a common view intialization you
583 use in your applications. You have a common doctype, <acronym>CSS</acronym> and
584 JavaScript, and you want to be able to pass in a base document title
585 via configuration. Such a resource plugin might look like this:
588 <programlisting language="php"><![CDATA[
589 class My_Resource_View extends Zend_Application_Resource_ResourceAbstract
593 public function init()
595 // Return view so bootstrap will store it in the registry
596 return $this->getView();
599 public function getView()
601 if (null === $this->_view) {
602 $options = $this->getOptions();
604 if (array_key_exists('title', $options)) {
605 $title = $options['title'];
606 unset($options['title']);
609 $view = new Zend_View($options);
610 $view->doctype('XHTML1_STRICT');
611 $view->headTitle($title);
612 $view->headLink()->appendStylesheet('/css/site.css');
613 $view->headScript()->appendfile('/js/analytics.js');
616 Zend_Controller_Action_HelperBroker::getStaticHelper(
619 $viewRenderer->setView($view);
621 $this->_view = $view;
629 As long as you register the prefix path for this resource plugin,
630 you can then use it in your application. Even better, because it
631 uses the plugin loader, you are effectively overriding the shipped
632 "View" resource plugin, ensuring that your own is used instead.