Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

New Proposal Under Consideration
This proposal has been rejected, but a new proposal is currently under consideration: Zend_Application - Ben Scholzen. Please see that proposal for current APIs and discussion.

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

Zend Framework: Zend_Application Component Proposal

Proposed Component Name Zend_Application
Developer Notes http://framework.zend.com/wiki/display/ZFDEV/Zend_Application
Proposers Bill Karwin
Revision 1.1 - 17 August 2006: Initial proposal posting. (wiki revision: 13)

Table of Contents

1. Overview

This is a proposal for a general-purpose bootstrap class for Zend Framework MVC applications. The objectives are (1) to implement a reusable and extensible class for bootstrapping web-based applications, and (2) establish a convention for configuration-driven application instances.

2. References

3. Component Requirements, Constraints, and Acceptance Criteria

  • Component will instantiate Zend_Controller_Front or user-specified front controller class.
  • Component will load config data from an array, file, or Zend_Config object and use the properties to configure the front controller.
  • Component will register the autoload callback of Zend_Loader or user-specified loader class.
  • Component will register a front controller plugin to load module-specific configuration files and process them with Zend_Application_Resource or user-supplied subclass of that component.
  • Component will support conventions for locations and names for config files, modules, controllers.
  • Component will proxy a run() method to the front controller, to dispatch web application requests.

4. Dependencies on Other Framework Components

  • Zend_Application_Resource
  • Zend_Config
  • Zend_Controller_Front
  • Zend_Loader
  • Zend_Registry

5. Theory of Operation

The Zend_Application class is a general-purpose, configurable bootstrap class. It configures an instances of Zend_Controller_Front, sets an autload callback, and dispatches to the front controller. The only parameter you are required to give to Zend_Application is the home directory of the application. Then use the run() method to start processing the request.

An example of the simplest usage of Zend_Application is the following:

The Zend_Application constructor processes the home directory argument with the realpath() PHP function. If this function determines that the path is invalid, a Zend_Application_Exception is thrown.

Using Config Files

Zend_Application attemps to read a "front" config upon startup. This config contains data specific to configuring the Front Controller and other resources that are application-wide, such as the Zend_Session.

Specify the config in the second constructor argument, or in the setConfig() method. You can specify the config in the following ways:

  • Zend_Config object instance - you can load the config file yourself in your bootstrap script, and pass the object to Zend_Application.
  • PHP array - you can declare a plain PHP array, so you don't have to write config data in a file at all.
  • Path to the config file.
  • Path to the directory containing the config file. The directory is searched for a file called 'config.ini' or 'config.xml'. The Zend_Config subtype is determined from the file extension. If more than one config.* file exists, it is non-deterministic which file is used, so it is best to specify the full filename. Only files named 'config.*' are searched; if you have a different filename, it is best to specify the full filename.
  • If you specify nothing, or a PHP null, this means to search the application home directory according to the behavior in the previous case.

In addition to the "front" config file, each application module may have its own config file. This config file specifies module-level resources and other module-specific data. Also, routes can be defined in each module's config file. Zend_Application includes a front controller plugin that loads the appropriate config files for a ll modules and adds all routes prior to routing. Then after routing, during the pre-dispatch step, the plugin processes other entries in the module's config file, so that resources are loaded only for the module to which the request is routed.

By default, this config file is located in a directory "config" which is a sister to the "controllers", "modules", and "views" directories.

The name of the "config" directory can be customized with a property in the front config file called 'moduleConfigDirectoryName', but that directory name is still relative to a given module's home directory.

Both .ini and .xml formats are supported.

Registering Autoloader

By default, Zend_Application registers an autoload callback, using Zend_Loader::registerAutoload().
You can specify properties 'autoloadEnabled' and 'autoloadClass' in the front config, to override the behavior of whether or not to enable autoloading, and the class to use for the autoload callback.

Also, if you subclass Zend_Application, you can specify different default values in the protected class members $_autoloadEnabled and $_autoloadClass

Configuring Zend_Application

Zend_Application uses config properties to declare customizations to the front controller and other application bootstrapping. None of the config properties are mandatory.

The following config properties are recognized:

Property Description
'applicationResourceClass' String names the class for the resource plugin to use to read module config files.
'autoloadEnabled' Boolean; enable the autoload callback if true. Default true.
'autoloadClass' String names the class to use for the autoload callback. Default Zend_Loader.
'baseUrl' String names the base URL of the application. This is passed to the front controller's setBaseUrl() method.
'configFile' String specify the modules' config file name, to be found by the front controller resource plugin.
'configSection' String specifies the config section to be read in the modules' config files.
'controllers' Array or Zend_Config object, maps one or more module names to their respective controller directories, in the manner supported by the front controller's setControllerDirectory() method.
'frontControllerClass' String names the class to instantiate the front controller. The class must be loadable and extend Zend_Controller_Front.
'modules' If this is the Boolean true value, the application support modules, and the modules are assumed to exist under the application home directory. If this is a string, array, or Zend_Config object, it maps one or more module names to their respective module directories, in the manner supported by the front controller's addModuleDirectory() method.
'moduleConfigDirectoryName' String names the directory for config files, under each module directory. Default is "config".
'moduleControllerDirectoryName' String names the directory for controllers, under each module directory. Default is "controllers".
'moduleModelDirectoryName' String names the directory for models, under each module directory. Default is "models".
'params' Array or Zend_Config object, maps parameter names to values, in the manner supported by the front controller's setParams() method.
'resourcePluginClass' String names the class to instantiate for processing module config files.
'returnResponse' Boolean; this is passed to the front controller's returnResponse() method.
'routes' Zend_Config object, contains a heirarchy of properties to declare routing rules for the front controller, in the manner supported by the rewrite router's addConfig() method.
'saveResourcesInRegistry' Boolean; this is passed to the Zend_Application_Resource class. Default is true.
'throwExceptions' Boolean; this is passed the the front controller's throwExceptions() method.

If any other customization of the front controller is needed, the developer can call the Zend_Application getFrontController() method to return the front controller object.

Creating Application Resources

Zend_Application includes a front controller plugin, called Zend_Application_Plugin. This plugin uses the proposed Zend_Application_Resource component. This component performs the following tasks prior to routing:

  • Read each module's config file.
  • Add all routes defined in the config files (this may supplement the routes defined in the front config file, or may be used instead of defining routes in the front config).

When a request is routed to a given module, additionally perform the following tasks:

  • Store the config object loaded from the module config dir in the registry, under registry key 'config'.
  • Instantiate resource classes declared in that config file.
  • Store the resources in the registry.

If the current request is in a non-default module, the config object and the resources instantiated by Zend_Application_Resource are stored in a new Zend_Registry object, which is in turn stored in the registry. The key for the new registry is the name of the module. This is to avoid key conflicts if two modules use the same key name.

Thus if a module named "blog" loads resources based on the module's config file, code within the blog module can retrieve a resource from the registry-within-a-registry as follows:

6. Milestones / Tasks

Milestone 1: [DONE] Publish proposal.
Milestone 2: Revise proposal, approve for Incubator development.
Milestone 3: Commit working prototype to Incubator.
Milestone 4: Commit working unit tests.
Milestone 5: Write end-user documentation.
Milestone 6: Release prototype in incubator.
Milestone 7: Revise implementation, tests, and documentation based on feedback.
Milestone 8: Merge changes from Incubator to Core.

7. Class Index

  • Zend_Application
  • Zend_Application_Plugin
  • Zend_Application_Exception
  • Zend_Application_Resource_FrontController

8. Use Cases

UC01: Bootstrap a simple web application
UC02: Specify a base URL for requests
UC03: Bootstrap script of web application with default module location
UC04: Adding a custom module location
UC05: Adding multiple custom module locations
UC06: Adding custom controller locations
UC07: Customizing the Front Controller
UC08: Declaring routes in an array
UC09: Declaring routes in a config file

front-config.ini:

index.php:

9. Class Skeletons

See proof-of-concept code and unit tests in the Zend Framework Laboratory. Check it out using Subversion (http://framework.zend.com/svn/laboratory), or browse it online using FishEye (http://framework.zend.com/fisheye/browse/Zend_Framework_Laboratory/library/Zend).

]]></ac:plain-text-body></ac:macro>

]]></ac:plain-text-body></ac:macro>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Aug 17, 2007

    <p>I've been working on something similar to this, but it's nice to see that zf will have an offical component to handle the bootstrap. Knowing bootstrap/configuration errors/exceptions can occur, I feel that some sort of errorHandler might be useful to either redirect to a static page etc.. At the moment some of us are doing something like this:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    try {
    /* BOOTSTRAP CODE HERE [...] */
    } catch (Exception $e) {
    // Debugging
    if ((bool) $appConfig->debug)

    Unknown macro: { throw $e; }

    // An exception has occured during setup, dispatch the SetupError Action of the Error Handling Controller.
    Zend_Loader::loadClass('ErrorController', rtrim($appConfig->paths->modules, '/
    ') . '/default/controllers');

    // Build request
    $request = new Zend_Controller_Request_Http();
    $request->setActionName('setupError')
    ->setParam('error_handler', new ArrayObject(
    array('exception' => $e,
    'type' => Zend_Controller_Plugin_ErrorHandler::EXCEPTION_OTHER), ArrayObject::ARRAY_AS_PROPS));

    $errorController = new ErrorController($request, new Zend_Controller_Response_Http());
    echo $errorController->run();
    exit();
    }
    ]]></ac:plain-text-body></ac:macro>

    1. Aug 20, 2007

      <p>This is difficult to make a generic error handler for exceptions encountered in the bootstrap process.</p>

      <p>What if the exception is due to the MVC framework itself failing? How can you redirect to an error display if that occurs? In the bootstrap code, the only thing we can be certain is working is the web server's ability to run a PHP script.</p>

      <p>So I would suggest we make a class Zend_Application_ErrorHandler, which does something like what you show above, but it also does its own exception catching, and redirects to config-specified static HTML page in case of catastrophe.</p>

  2. Aug 18, 2007

    <p>My bootstraps were getting bloated and repetitious. I had a go at creating an application class. I found it troublesome in practice when trying to accommodate different set ups like for example using some of the code in current proposals where special set ups can be needed.</p>

    <p>So I re-wrote it as an entirely static helper class and that seems to be working out. It allows me to cut down on the bootstrap bloat while retaining flexibility.</p>

    <p>My failure at an instantiated approach could have been just inadequate design. I just wanted to share my experience, and look forward to seeing how this proposal goes.</p>

    <p>Here's the methods I'm using if it's of any interest (not pretty enough to show in full):<br />
    <ac:link><ri:page ri:content-title="CODE" /></ac:link><br />
    public static function customizePhpBehaviour($appDir = null, $configEnv = null)<br />
    public static function prependIncludePath($path)<br />
    public static function getAppDir()<br />
    public static function getAppDirAssumingSelfUnderPublicDir()<br />
    public static function getConfigEnv()<br />
    public static function isProductionServerDetected()<br />
    public static function customizePhpErrorReporting($configEnv)<br />
    public static function checkVersionRequirements($options)<br />
    public static function getAppName()<br />
    public static function boot($appDir = null, $configEnv = null)<br />
    public static function bootstrapZendFramework($appDir = null, $configEnv = null)<br />
    public static function runApp()<br />
    public static function initRegistry($appDir = null, $configEnv = 'production')<br />
    public static function setupController($request = null, $response = null)<br />
    public static function portablePath($path)<br />
    <ac:link><ri:page ri:content-title="/CODE" /></ac:link></p>

    1. Aug 20, 2007

      <p>Right – using an object-oriented approach can help with reducing bloat. </p>

      <p>The proposal shows how we can achieve great flexibility and customization, using a mix of several programming mechanisms:</p>

      <ul>
      <li>Object-oriented extensibility (i.e. subclassing)</li>
      <li>Configuration specified in config files</li>
      <li>Configuration by method calls and parameter values</li>
      <li>Plugin architecture to enable extra functionality (see proposal for Zend_Application_Resource)</li>
      </ul>

  3. Aug 20, 2007

    <p>Would it be possible to include a method so that it could create a Zend_Cache_Page() object? Like so:</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $frontendOptions = array('lifetime' => 7200,
    'debug_header' => true,
    'regexps' => array('^/$' => array('cache' => true)));

    $backendOptions = array('cache_dir' => '/tmp/');

    $app = new Zend_Application('/path/to/app/home');
    $app->cache('Page', 'File', $frontendOptions, $backendOptions);
    $app->run();
    ]]></ac:plain-text-body></ac:macro>

    <p>Either that or it would be great to allow an init() method (similar to the Controller, Db classes) for user-defined hooks that fire off after construction so that objects like this could be created within a sub-classed instance of Zend_Application.</p>

    <p>Will the path parameters supplied to Zend_Application be converted to realpaths during processing? I find it a bit less verbose and more elegant to supply:-</p>

    <p>'../application/controllers' </p>

    <p>than</p>

    <p>dirname(dirname(<em>FILE</em>) . '/application')</p>

    <p>One last feature request would be to auto-discover an environment based on its server name or IP address. That way you can pass 'production' or 'development' to your Zend_Config_Ini file without needing to hardcode it into your bootstrap - handy if you're sharing a site in a number of different locations simultaneously. I've got the code for this sitting in the Zend_Environment component if you're interested.</p>

    1. Aug 20, 2007

      <p>Regarding Zend_Cache_Page:</p>

      <p>You should take a look at the <a href="http://framework.zend.com/wiki/x/lY4">Zend_Application_Resource</a> proposal. That's my intended solution to enable user-defined plugins for the application bootstrap process. So we would write a class that extends Zend_Application_Resource_Abstract, for example we could call it Zend_Application_Resource_Cache_Page.</p>

      <p>The presence of this class would implicitly mean that a config file could contain properties with the config data to be passed to Zend_Application_Resource_Cache_Page. That class would contain the logic to map config data to the Zend_Cache factory.</p>

      <p>Note the config data doesn't necessarily have to be passed verbatim to the Zend_Cache factory; the resource manager class gets to interpret the config data and do the right work to create the object.</p>

      <p>Using this kind of plugin architecture, I hope we can avoid adding lots of special-case hooks to Zend_Application. The plugins would be loaded automatically on demand, based on the values found in the config files. Thus the base Zend_Application class would remain pretty lean.</p>

    2. Aug 20, 2007

      <p>Regarding realpath and using ".." instead of dirname():</p>

      <p>Sure, we can call realpath on the home directory specified. That way the bootstrap could use relative paths easily. And if an absolute path were specified, that'd work too.</p>

    3. Aug 20, 2007

      <p>Regarding discovery of environment and corresponding config section:</p>

      <p>We've been talking about this internally a bit. There are several ways to do this, with different advantages and disadvanteges.</p>

      <p>1. Declare instance name in php.ini, retrieved with <code>ini_get()</code></p>

      <p>Advantage: portable, centralized.<br />
      Disadvantage: users often don't have access to edit php.ini. If you need to deploy many apps, this could create an explosion of php.ini directives.</p>

      <p>2. Define PHP variable directly in bootstrap script</p>

      <p>Advantage: portable, flexible, keeps config in pure PHP code instead of involving other types of environmental config.<br />
      Disadvantage: requires editing application bootstrap on each deployed instance. The app code should be under revision control, so the bootstrap file would show up as locally modified, and this is confusing.</p>

      <p>3. Use superglobals <code>$_SERVER['HTTP_HOST']</code> or <code>$_SERVER['SERVER_NAME']</code></p>

      <p>Advantage: mostly portable, keeps config away from bootstrap code.<br />
      Disadvantage: breaks if the hostname or virtual host name changes. Also if two hosts need the same config section, you have to create duplicate sections for no reason.</p>

      <p>4. Use environment variable, set in Apache with the <code>SetEnv</code> directive, either in the global httpd.conf or in .htaccess or else set in system configuration and passed to web app with the Apache <code>PassEnv</code> directive.</p>

      <p>Advantage: isolates instance variable from application code.<br />
      Disadvantage: specific to web server and deployment technology (Apache, mod_php, fastcgi, isapi, etc.). Also, the web server config should be under revision control as well.</p>

      <p>5. Declare instance name in a one-line config file</p>

      <p>Advantage: portable, good for users without access to php.ini.<br />
      Disadvantage: performance cost of reading an extra unnecessary file. Also, it doesn't implicitly change as you deploy to a different server, so one could accidentally deploy the wrong config.</p>

  4. Aug 23, 2007

    <p>I noticed several bugs in the attachment, one was in the Application.php at ~108<br />
    missing </p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[return self::_doLoadConfig($path, $type, $section);]]></ac:plain-text-body></ac:macro>

  5. Aug 23, 2007

    <p>Also, I am not sure about relative paths when using ZA with the cli as the paths are changed to where the current dir is.</p>

    <p>It might be a good idea to append the home directory instead for modules and any other paths that are relative for the cli.</p>

    <p>Another thing I thought about was setting the home dir as the default module directory. Wouldn't it be better if the default was something like $appHomeDir . 'modules' as a home directory does have other folders than module specific stuff.</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    protected function _setModules(Zend_Controller_Front $front, $modules)
    {
    if ($modules === true)

    Unknown macro: { $modules = $this->_appHomeDirectory; }

    else if ($modules instanceof Zend_Config)

    Unknown macro: { $modules = $modules->toArray(); }

    ]]></ac:plain-text-body></ac:macro>

  6. Aug 27, 2007

    <p>I think 'autoloadEnabled' should not be enabled by default since autoloading prevents opcode caches from doing their work on autoloaded files.</p>

    1. Aug 28, 2007

      <p>This point about autoloading is a good point, so I consulted an expert who works on Zend Platform.</p>

      <p>It is not true that autoloading is incompatible with opcode caching. It works fine. There are cases when a class cannot be cached, but these cases happen whether you use autoload or not.</p>

      <p>The performance difference between using autoload vs. require_once is not significant for most applications. If your application is so sensitive the performance impact of using autoload matters, then it's much more likely that other system architecture changes will help to a much greater degree than micro-optimizing class loading.</p>

      <p>The bottom line is that using autoload makes development easier, and this outweighs its potential disadvantages.</p>

      <p>If you still want to set autoload to false, there are at least two alternatives to accomplish this:</p>

      <ul>
      <li>Specify the <code>autoloadEnabled</code> option to the constructor of the Zend_Application class:
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      $app = new Zend_Application($homeDir, array('autoloadEnabled' => false));
      ]]></ac:plain-text-body></ac:macro></li>
      </ul>

      <ul>
      <li>Create your own extended Zend_Application class and change the default:
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      class My_Application extends Zend_Application
      {
      protected $_autoloadEnabled = false;
      }
      ]]></ac:plain-text-body></ac:macro></li>
      </ul>

  7. Aug 28, 2007

    <ac:macro ac:name="note"><ac:parameter ac:name="title">Prototype Code Moved</ac:parameter><ac:rich-text-body>
    <p>I have removed the attached Zip file from this proposal page, and instead checked the proof-of-concept code into svn in the ZF Laboratory:
    <a class="external-link" href="http://framework.zend.com/svn/laboratory">http://framework.zend.com/svn/laboratory</a></p>

    <p>Zend_Application code and tests are under <code>library</code> and <code>tests</code>.</p></ac:rich-text-body></ac:macro>

  8. Aug 28, 2007

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    protected static function _doLoadConfig($path, $type, $section)
    {
    $configClass = 'Zend_Config_' . ucfirst($type);
    Zend_Loader::loadClass($configClass);
    $config = new $configClass($dir . DIRECTORY_SEPARATOR . $file, $section);
    if (!$config instanceof Zend_Config)

    Unknown macro: { require_once 'Zend/Application/Exception.php'; throw new Zend_Application_Exception("Class '$configClass' does not extend Zend_Config"); }

    return $config;
    }
    ]]></ac:plain-text-body></ac:macro>

    <p>$dir . DIRECTORY_SEPARATOR . $file should be $path</p>

    1. Aug 28, 2007

      <p>Thanks Geoffrey, yes, I noticed that mistake too. I'm working on it now, and I corrected that issue as I'm writing a few more unit tests.</p>

      <p>The code is just in proof-of-concept phase, to illustrate the proposal. I'm trying not to work too hard on it, in case the proposed architecture is rejected. <ac:emoticon ac:name="smile" /></p>

  9. Aug 28, 2007

    <p>Thanks, I'm just trying out the component in a simple test application. It's a step forward, but I think it still needs more hooks.</p>

    <p>btw, the construct in Zend_Application_Plugin conflicts when used with modules because it tries to load a module config before the module directory is set and before the dispatch() process has started.</p>

    1. Aug 28, 2007

      <p>Can you describe examples of what type of hooks are needed?</p>

      <p>Also keep in mind that you can always do <code>$app->getFrontController()</code> and then do less common types of customization. The Zend_Application interface, like most components in ZF, should provide a simple solution for the 80% most common usage, and then allow for extensibility for other more exotic cases.</p>

  10. Aug 29, 2007

    <p>I found a wee bug in the _doLoadConfig() method. Instead of</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $config = new $configClass($path, $section);
    ]]></ac:plain-text-body></ac:macro>
    <p>...it should be</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $config = new Zend_Config(new $configClass($path, $section));
    ]]></ac:plain-text-body></ac:macro>
    <p>...otherwise you never end up with a Zend_Config object.</p>

    <p>Also, there's a test for the 'config' filename using the 'filename' property of pathinfo. Is it possible to use a strpos or something similar for all us non-5.2.0 users? <ac:emoticon ac:name="wink" /></p>

    <p>Finally I'm trying to put together the relationship between the Zend_Application and the Zend_Application_Resource family. Is it true to say that just by having the 'db' key set in my config that a Zend_Db object is auto-created or do I have to initiate that manually?</p>

    1. Aug 30, 2007

      <ul>
      <li>You don't get an object for which <code>get_class($config) == 'Zend_Config'</code>, but you do get an object that passes the test <code>$config instanceof Zend_Config</code>.</li>
      </ul>

      <ul>
      <li>Apologies for the <code>pathinfo()</code> usage. I will change it to work with PHP 5.1.4.</li>
      </ul>

      <ul>
      <li>Yes, the idea is that Zend_Application iterates through each module's config file and if it finds config properties that match a certain naming convention, <strong>and</strong> a corresponding wrapper class exists that extends Zend_Application_Resource_Abstract, then the config data is used to instantiate that resource.</li>
      </ul>

  11. Aug 29, 2007

    <p>Oh and another - the '_config' always seems to be null. I'm guessing that's because the Zend_Config object is always out of scope?</p>

    1. Aug 30, 2007

      <p>I don't understand what context you're referring to. The <code>$_config</code> object in Zend_Application is set in the constructor, or with the <code>setConfig()</code> method.</p>

      1. Aug 30, 2007

        <p>Indeed it is but in PHP 5.1.6 all I'm seeing is a null value in that property. I'm guessing there's a slightly revised handling of class/object contexts in PHP 5.2.0? I was testing my config file and sure enough it is being correctly read and parsed in the static _loadConfig methods, but when it is passed back to the setConfig() method it is a null value, so I've assumed that the Zend_Config object has gone out of scope. Try it in PHP 5.1.6 and you'll see what I mean.</p>

        1. Aug 30, 2007

          <p>Okay, thanks that helps. I got PHP 5.1.6 installed and saw the errors related to <code>pathinfo()</code> you mentioned. I fixed those, and that may have resolved the <code>null</code> returned by <code>_doLoadConfig()</code> too. I made sure there's an object returned to <code>setConfig()</code>. Can you update in zflab and try it now?</p>

  12. Aug 30, 2007

    <p>Bill – This looks good. I have a few notes:</p>
    <ul>
    <li>Allow config.php
    <ul>
    <li>This allows those of us who like using arrays for configs to do so</li>
    </ul>
    </li>
    <li>Does application module config <strong>need</strong> to be in a separate directory?
    <ul>
    <li>Seems like having it at the toplevel of the module would be sufficient</li>
    </ul>
    </li>
    <li>Need configuration for:
    <ul>
    <li>Plugins
    <ul>
    <li>Should allow specifying either:
    <ul>
    <li>Directory of plugins to load</li>
    <li>array of plugin => path values</li>
    </ul>
    </li>
    </ul>
    </li>
    <li>Action Helpers
    <ul>
    <li>Should allow specifying:
    <ul>
    <li>prefix => path pairs for action helper paths</li>
    <li>class => path pairs of specific helpers
    <ul>
    <li>should allow a second argument to load at start</li>
    </ul>
    </li>
    </ul>
    </li>
    </ul>
    </li>
    </ul>
    </li>
    <li>Should allow specifying:
    <ul>
    <li>error controller to use (pass to error handler plugin)</li>
    <li>view class/object to use with ViewRenderer</li>
    <li>Eventually: whether or not to use layout, and layout config options</li>
    </ul>
    </li>
    </ul>

    1. Aug 30, 2007

      <ul>
      <li>config.php would be solved transparently if we had a Zend_Config_Php class.</li>
      <li>No, module config doesn't need to be in a separate directory.
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      $app = new Zend_Application($homeDir, array('modules'=>true, 'moduleConfigDirectoryName'=>''));
      ]]></ac:plain-text-body></ac:macro></li>
      <li>Plugins and Action Helpers, including Error Handler and ViewRenderer options, should be configured by manipulating the Front Controller object returned by the <code>getFrontController()</code> method.</li>
      <li>Layout config is probably a common enough usage requirement that we can add options to Zend_Application_Resource_FrontController to handle this.</li>
      </ul>

      1. Sep 03, 2007

        <p>We used to have Zend_Config_Array, but it was pulled on the grounds that it did nothing <ac:emoticon ac:name="smile" /></p>

        <p>Rob...</p>

  13. Aug 30, 2007

    <p>Hey Bill,</p>

    <p>Reviewing this I am questioning if this really makes sense. From a performance perspective this is a heck of a lot of overhead for gains which could be achieved using other approaches. I agree in principal with what Zend_Application is looking to accomplish, however your approach pushes what appears to be really a "one time" process (setting up an generic application) into a every-request series of events within the bootstrap. Even if you were to employ caching mechanisms its still completely unnecessary overhead.</p>

    <p>I think these concepts (setting up the FC, error handling, configuration, etc) should all be done using a code-generation approach rather then a runtime Zend_Application class. A code generation approach would accomplish all of the same tasks without the runtime overhead. You could even use a lot of the same configuration notions described in this document to dictate how the code generation is to occur and achieve the exact same functionality without unnecessary runtime overhead. The only difference would be that any generated code would have to be considered "read only" by the application and any customization beyond that which is provided for by the code generator must be done via class extension (to allow re-generation of the base application framework if desired).</p>

    <p>I know that I personally would never use a tool like this in Global Services as it is proposed because while it does save me time as a developer I can't justify adding such overhead to every single request. That's why I originally proposed something like Primitus, which would accomplish the same task but added no overhead then what was already required by Framework itself.</p>

    <p>John</p>

    1. Aug 30, 2007

      <p>I'd be interested to hear what parts of Zend_Application you believe incur more overhead compared to a bootstrap script that configures the app with equivalent options.</p>

      <p>I just ran my current collection of Zend_Application unit tests with "<code>phpunit --repeat 1000</code>". It executed 39000 tests in 153 seconds. So that's 254 tests per second, or less than 0.004 seconds per test. This <em>includes</em> the overhead of PHPUnit, and my test environment does <em>not</em> make use of any opcode cache.</p>

      <p>Running the single unit test that reads an XML config file from disk (<code>testApplicationSetConfigString()</code>), repeated 10000 times. It executed 10000 tests in 40 seconds, which is 250 tests per second, or 0.004 seconds per test.</p>

  14. Aug 30, 2007

    <p>I agree with john, it's too much overhead, my vote goes for a code-generation approach.</p>

    1. Aug 30, 2007

      <p>I don't want to seem like I'm being too precious about my proposal, but I don't think the overhead of this solution is significantly more than a plain bootstrap script. </p>

      <p>In cases like this, we need to use performance measurements to provide evidence one way or the other. That's the only way to make a decision. We can't make progress simply by making assumptions.</p>

      1. Oct 19, 2007

        <p>I agree with Bill. The files output by the code generator would have to be executed on every request anyway, just like the Zend_Application code. The performance difference between the two pieces of code is likely to be negligible. The most likely bottle neck would be file system access to config files, etc. If it's a problem, you-<span style="text-decoration: line-through;">like Bill said</span>-should benchmark it and deal with what's actually slow.</p>

  15. Aug 31, 2007

    <p>I like such class. I don't think overhead would be that big (should be checked of course <ac:emoticon ac:name="smile" /> and I think most people would use defaults anyway, so it would look really easy and nice. We need to document the defaults extensively of course, so people would know how to build their app in a way that would "just work".</p>

  16. Aug 31, 2007

    <p>I'm using Zend_Application now in a smaller project and whilst the initial setup was a bit mystifying, now that I've grasped how Zend_Application and Zend_Application_Resource work together it's lovely and smooth.</p>

    <p>Perhaps it would also be nice to add the following properties to make it an all-in-one solution:-</p>
    <ul class="alternate">
    <li>Default timezone set by config e.g. date_default_timezone_set('Australia/Melbourne');</li>
    <li>Default language set by config (or default Zend_Locale)</li>
    </ul>

    <p>I'm in favour of this kind of approach for the 80/20 case. There's so many sites that don't require a complete re-working/re-coding to simply set up MVC and a few connections. Like the above example, I'm not seeing a huge performance hit and if the Zend_Application_Resource_Cache is implemented, or a Zend Platform-type accelerator is used then it's also less of a performance issue.</p>

  17. Sep 01, 2007

    <p>Another thing I'm confused about is, how would you organize resources? Like a db resource, which might have something like a profiler. I guess the profiler could be considered part of the db resource though. Perhaps this, how would I handle a resource that sets a custom view obj to viewRenderer or setting helper paths to the action helper broker etc..</p>

    1. Sep 01, 2007

      <p>Specifying a Db profiler can be done using options to the <code>Zend_Db::factory()</code> method, or using the Db adapter method <code>setProfiler()</code> after the adapter is instantiated.</p>

      <p>Advanced options of the front controller, like custom view renderer or helper paths, should be done with the Zend_Controller_Front object returned by <code>Zend_Application::getFrontController()</code>. The idea of the Zend_Application is not to duplicate every option, but to make it very convenient to configure the options you would use most frequently.</p>

      1. Sep 02, 2007

        <p>Wouldn't specifying helper paths be considered a frequently used option? I don't know about other people, but on just about every application, I've specified paths to my library. Helpers like Xend_Layout and a baseUrl helper etc... are useful. Zend_Layout if accepted brings another question about resources since it needs to be setup before dispatch(). Would this component be setup via Zend_Application or would we have to do this manually?</p>

  18. Sep 17, 2007

    <p>have you thinked about implementing unique error handling ? stupid name, what i mean is that it would be great to have one point where ALL errors go (ErrorController), also when the error happens in application init, or in views (or all other parts of the application). I currenty do something like this for a current application. I also convert php errors into exceptions. the only thing left seems how to handle the exceptions inside views when using the viewRenderer. at the moment i tend to just not use the viewrenderer and render for my own to catch the exceptions.</p>

    <p>maybe we can share code ?</p>

  19. Sep 21, 2007

    <p>I would enjoy a config option which makes the routing "language aware" in such manner:</p>

    <p>/en/module/controller/action<br />
    /fr/module/controller/action<br />
    /de/module/controller/action</p>

    <p>This will also prevent developers form writing multilingual applications, which renders many languages at the very same URL and keeping language infos in the session or cookies. Another advantage could be the option to create language files (maybe array based) for all the validation messages and bundle these translations to Zend_Validate.</p>

  20. Nov 11, 2007

    <p>Why only config of module?</p>

    <p>What if I create view helper of blog module and I need some conguration data, but I'm using it i the view of other module action (or even layout, its the same)</p>

    1. Nov 11, 2007

      <ac:macro ac:name="note"><ac:parameter ac:name="title">Proposal Rejected</ac:parameter><ac:rich-text-body>
      <p>This proposal did not meet the goals of the Zend Framework project and further development on it has been rejected.</p></ac:rich-text-body></ac:macro>