Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="toc"><ac:parameter ac:name="type">list</ac:parameter><ac:parameter ac:name="maxLevel">3</ac:parameter></ac:macro>

<ac:macro ac:name="note"><ac:parameter ac:name="title">Participate in the Discussion</ac:parameter><ac:rich-text-body>
<p>Please participate in the discussion! You can either do so in comments to these pages, or by subscribing to the zf-contributors@lists.zend.com – simply send an email to zf-contributors-subscribe@lists.zend.com!</p></ac:rich-text-body></ac:macro>

<p>Zend Framework has grown substantially and organically throughout the 1.X series of releases.</p>

<p>The result has been a framework that is immensely powerful, broadly appealing, and enormous in scope – but also one that is cumbersome and difficult to learn, distribute, and extend, and one that is becoming less and less performant. Additionally, since Zend Framework has experienced large adoption, this has led us to re-evaluate a number of design decisions – but the inability to break backwards compatibility has made it impossible or difficult to create better implementations.</p>

<p><strong><em>The primary thrust of ZF 2.0 is to make a more consistent, well-documented product, improving developer productivity and runtime performance</em></strong>.</p>

<p>The following document serves as a narrative detailing the various goals of Zend Framework 2.0. We will be gradually filling in an implementation plan for each set of goals so that we can measure the success of the effort.</p>

<h2>General Goals</h2>

<ul>
<li>Ease the learning curve</li>
<li>Make extending the framework trivially simple</li>
<li>Improve baseline performance of the framework</li>
<li>Simplify maintenance of the framework for the core team and contributors</li>
<li>Be an exemplar of PHP 5.3 usage</li>
<li>Provide mechanisms for using just the parts of the framework needed</li>
</ul>

<h3>Ease the learning curve</h3>

<p>In late 2009, we did a survey of framework users to determine what they use,<br />
what environments they use, and what their needs are. The top issue, bar none,<br />
was the difficulty of learning the framework. Some of these issues include:</p>

<ul>
<li>Difficulty in the "first hour" with the framework. Many of these questions have been addressed in the revised "Quick Start" shipped with 1.10, but additional issues remain: how to setup vhosts on non-Apache web servers, how to follow the quick start without a dedicated vhost, and problems arising from differences in operating environments.</li>
<li>Uncertainty about the "next steps" following the quick start. Developers are unsure how to go about using different components to create a cohesive application. Again, first steps at alleviating this concern have been taken with 1.10 with the "Learning Zend Framework" section of the manual. However, these are largely disparate tutorials, and don't show full development on a single application.</li>
<li>Inconsistent APIs in the source code itself. One component may use "plugins," another "helpers," and yet another "filters." One component may utilize fluent interfaces, another not. One component may allow <code>MixedCase</code> plugin names, while another only allows <code>Titlecased</code>. One component may use a broker for accessing helpers, while another delegates to them via <code>__call()</code>. One component may allow <code>camelCasedOptions</code>, while another only allows <code>underscore_separated</code>. One component may allow passing an array of options only, while others allow passing an array or a <code>Zend_Config</code> object. The list can go on for quite some time.</li>
<li>Uncertainty about where extension points exist, and how to program for them.</li>
<li>Confusion over whether they can use Zend Framework only as an MVC stack or as individual components.</li>
</ul>

<h4>Goals</h4>

<ul>
<li><strong>MUST</strong> create two separate quick start tutorials: one that covers using individual components of Zend Framework, and another covering creation of a basic MVC application. In both cases, the tutorials:
<ul>
<li><strong>MUST</strong> explicitly indicate the expectations of developer knowledge. E.g., "developer should be familiar with PHP 5, OOP, and have a basic understanding of autoloading; additional, some knowledge of Apache and configuring virtual hosts is assumed."</li>
<li><strong>MUST</strong> have reproducible steps that, if followed, will return the same results. Minor variations for common operating system environments <em>should</em> be covered (e.g., differences between linux, mac, and windows environments).</li>
<li><strong>MUST</strong> clearly identify the next steps a developer should take, and link to related references.</li>
</ul>
</li>
<li>Development of a set of cohesive tutorials covering intermediate and advanced Zend Framework topics. To achieve this we:
<ul>
<li><strong>MUST</strong> identify common development problems for Zend Framework, and the most common patterns used to address them.</li>
<li><strong>MUST</strong> write a sample application that illustrates these problems and solves them using the patterns identified.</li>
<li><strong>MUST</strong> have a clear narrative showing step-by-step construction of the application, one problem/pattern at a time.</li>
</ul>
</li>
<li>The reference manual:
<ul>
<li><strong>MUST</strong> clearly state the assumptions and use cases for each component. As an example, the various <code>url()</code> helpers currently allow passing a named route as an option. However, many developers do not understand that if none is provided, then it will use the currently matched route. This leads to a difference between developer expectations and code expectations, which has led to a number of issues in the tracker. Simply documenting these, as well as concise use cases, should alleviate the issues.</li>
<li><strong>MUST</strong> have consistent formatting for each component, for predictability.
<ul>
<li><strong>SHOULD</strong> provide an overview</li>
<li><strong>SHOULD</strong> provide expected arguments and return values, as well as exception conditions</li>
<li><strong>SHOULD</strong> provide one or more usage examples</li>
<li><strong>COULD</strong> provide narrative, but does not need to</li>
</ul>
</li>
</ul>
</li>
<li>Address the various API consistency issues:
<ul>
<li><strong>MUST</strong> standardize option casing</li>
<li><strong>MUST</strong> standardize language and APIs surrounding the various extension points</li>
<li><strong>SHOULD</strong> attempt to standardize APIs for passing options to components</li>
<li><strong>SHOULD</strong> attempt to identify and implement common API patterns throughout the framework</li>
</ul>
</li>
</ul>

<h3>Make extending the framework trivially simple</h3>

<p>Extending Zend Framework is relatively easy already. However, there are a few notable cases where it is difficult, and some of these cases are found in many places in the framework.</p>

<p>These include:</p>

<ul>
<li><em>Singletons</em>. Many singletons have a lot of behavior coded into them, making it difficult, if not impossible, to provide alternate implementations. Examples include <code>Zend_Controller_Front</code>, <code>Zend_Auth</code>, and <code>Zend_Session</code>.</li>
<li><em>Use of abstract classes instead of interfaces</em>. Many ZF components define rich abstract classes with a plethora of behaviors. While these may be extended and alternate implementations provided, doing so often requires accepting functionality you don't need, or needing to overwrite large sets of functionality you don't want. In many cases, the consuming classes only rely on a small subset of behaviors.</li>
<li><em>Hard-coded dependencies</em>. In many cases, components have hard-coded dependencies, making it impossible to alter behavior without extending the class to add your own dependency or to allow injecting the dependency.</li>
<li><em>Failure to identify processes that could benefit from collaborators</em>. As an example, many of <code>Zend_Db</code>'s methods could benefit from user extension – for instance, to allow checking for and writing to a cache, normalizing values prior to insertion, etc. In order to do this now, users must extend the existing classes, leading to difficult to traverse hierarchies and reducing re-usability. A plugin/filter system could alleviate these issues easily.</li>
</ul>

<h4>Goals</h4>

<ul>
<li><strong>MUST</strong> Eliminate singletons where possible; when not possible, push behavior into collaborating objects.</li>
<li><strong>MUST</strong> identify the essential interfaces for each component and subcomponent, and typehint on these instead of the existing abstract classes.</li>
<li><strong>MUST</strong> remove hard-code dependencies and allow for dependency injection.</li>
<li><strong>MUST</strong> examine each component and address the need for collaborators.</li>
<li><strong>SHOULD</strong> add a section to the documentation for each component, showing in a consistent structure the component's support for extension, plugins, and hooks.</li>
</ul>

<h3>Improve baseline performance of the framework</h3>

<p>Baseline performance of Zend Framework applications has been getting worse with almost every release; even when gains are made, new processes added in new releases lead to degradation. While ZF started as a fairly nimble framework, it is now among the slower alternatives available, when using the supplied MVC stack.</p>

<p>The goal of ZF 2.0 is to identify causes of performance issues and implement code changes to mitigate them until ZF is competitive with any other PHP framework of similar capabilities.</p>

<h4>Goals</h4>

<ul>
<li><strong>MUST</strong> improve the baseline performance by 200-300% over the 1.x series, and competitive with the more agile full-stack frameworks currently available, including Solar and Symfony 2.</li>
<li><strong>MUST</strong> provide deployment-time tools for optimizing performance in production</li>
<li><strong>MUST</strong> provide documentation, tutorials, and examples to help developers follow best practices for performance.</li>
</ul>

<h3>Simplify maintenance of the framework</h3>

<p>As of the time of this writing, Zend Framework consists of over 2 million lines of code, including over 14k unit tests. The internal team at Zend consists of a project lead and two engineers, while actual contributors number in the dozens. Contributors come and go, largely based on their interest in specific components and the time they have to devote to the project. High turnover of maintainers and lack of availability from maintainers, both internally and amongst contributors, has led to many orphaned components and/or components with large numbers of issues filed against them.</p>

<p>Additionally, with the growing complexity of many of the components, often due to differing expectations between different end-users and the original designs, we often get internal conflicts within components, where resolving one issue or addressing one feature requests can spawn regressions for existing functionality.</p>

<p>Another barrier has been actually getting contributions <em>into</em> the framework. Currently, we only offer SVN access on a case-by-case basis, which leads to developers posting patches as comments or attachments to the issue tracker. Often, the best way to really evaluate these patches is to apply them and run unit tests – and this method of obtaining the patches is inefficient. </p>

<p>When it comes to writing patches, many developers are unsure how to do so, or where in the tree to generate the diffs. As a result, often the patches submitted need to be doctored in order to be usable. Subversion does not help here, as <code>svn diff</code> can be done at arbitrary levels, and will not diff from the tree root.</p>

<p>Collaborating on complex components or component development is also often difficult, as there are no good conventions for maintaining separate branches in the ZF repository. As a result, many developers will do feature/component development in their own version control systems, and point developers to these to test. This can lead to overhead if they use a different class prefix during development versus once the component is pushed into the ZF repository, as well as if the original development is done in a different version control system.</p>

<p>Finally, there are a number of components for which 3rd party code offers more comprehensive solutions. Users may turn to these, or compare ZF components with them when evaluating solutions to their application needs.</p>

<h4>Goals</h4>

<ul>
<li><strong>SHOULD</strong> migrate to a distributed version control system
<ul>
<li><strong>SHOULD</strong> be a system many ZF developers are already familiar and/or *comfortable with</li>
<li><strong>SHOULD</strong> have the ability to specify multiple remotes per local repository</li>
<li><strong>SHOULD</strong> create patches from the repository root by default</li>
<li><strong>SHOULD</strong> support some method of verifying committer identity, to allow easy verification of CLA status when merging to the canonical repository</li>
</ul>
</li>
<li><strong>SHOULD</strong> include well-defined interoperability and compatibility with existing third-party libraries and frameworks.
<ul>
<li>This <strong>COULD</strong> be via consuming these third-party solutions</li>
<li>This <strong>SHOULD</strong> include helping define and follow interoperability standards, such as the common naming schema to allow common autoloading capabilities.</li>
</ul>
</li>
</ul>

<h3>Be an exemplar of PHP 5.3 usage</h3>

<p>One goal of Zend Framework was to advance the usage of PHP 5 and establish best practices surrounding the usage of PHP 5. To a large extent, ZF has achieved this goal (along with a handful of other projects).</p>

<p>PHP 5.3 was released mid-2009, and with it a myriad of new features were introduced: closures/lambdas, namespaces, late static binding, goto, and more. Many of these new features were introduced at the insistence of framework developers, as they can assist in making code more maintainable, concise, and readable.</p>

<p>Simply stated, Zend Framework 2.0 <strong>MUST</strong> be an exemplar of PHP 5.3 usage.</p>

<h4>Goals</h4>

<ul>
<li><strong>MUST</strong> use namespaces throughout the framework, to mitigate naming collisions with userland code and third-party code.</li>
<li><strong>MUST</strong> remove all <code>create_function()</code> constructs and replace them with closures</li>
<li><strong>MUST</strong> evaluate the framework to identify areas that could benefit from other new language features.</li>
<li><strong>MUST NOT</strong> use new language features just for the sake of using them. They should be utilized only where they make sense.</li>
<li><strong>SHOULD</strong> be a showcase for improving code through refactoring, which is itself a strength of PHP.</li>
</ul>

<h3>Provide mechanisms for using just the parts of the framework needed</h3>

<p>One criticism often levied against Zend Framework is that it is "bloated." In most cases, the accusers are critical of the shear breadth of the framework – they do not want to install the entire code base when they only need one or a handful of components from it.</p>

<p>Additionally, many developers are using individual Zend Framework components within larger applications, sometimes written in other frameworks. ZF should support and encourage such use cases, and make it trivially easy for developers to fetch the components they wish to integrate.</p>

<p>On a related note, when pushing an application to production, often there are huge swaths of the framework that must be pushed that will never, ever be used, which wastes bandwidth, time, and disk space.</p>

<p>We have traditionally shipped the entire framework because it makes sense to have the entire framework available; if you need a component, you don't need to fetch it before using it. However, with the shear breadth of the framework, and the many uses to which developers are putting it, the time has come to enable developers to select individual components.</p>

<h4>Goals</h4>

<ul>
<li><strong>MUST</strong> provide code infrastructure to support packaging
<ul>
<li><strong>MUST</strong> use namespaces and good component design to ensure components are properly encapsulated</li>
<li><strong>MUST</strong> write tools that can automatically determine dependencies for components</li>
<li><strong>SHOULD</strong> write tools for automatically creating packaging information (e.g., files necessary, component name, release version, etc.)</li>
</ul>
</li>
<li><strong>SHOULD</strong> create a PEAR and/or Pyrum channel for distributing packages
<ul>
<li><strong>SHOULD</strong> create a number of meta-packages or bundles for common functionality; e.g., "MVC", "I18n", etc.</li>
</ul>
</li>
</ul>

<h2>Development Objectives</h2>

<ul>
<li>Simplify</li>
<li>Programming by Contract</li>
<li>Favor the explicit over the magical</li>
</ul>

<h3>Simplify</h3>

<p>Zend Framework is often accused of being "bloated". When pressed, those who claim this will point to two factors: overall size of download, and the fact that most ZF components try to cover absolutely every use case possible, while specializing in none. The first factor is a straw-man; with a comprehensive framework such as Zend Framework, one <em>should</em> expect the download size to be fairly large. </p>

<p>The second factor, however, is very much accurate. It is also the source of our large number of issue reports. Developers consistently want a component to cover "just one more" use case, and adding support for it may then lead to inconsistent or undesired behavior in other use cases, leading to a spiral increase in reports.</p>

<p>Additionally, we have maintained a number of "hacks" and structures within the framework that can either be eliminated or replaced with language features available in PHP 5.3.</p>

<h4>Focus on Core Components</h4>

<p>Our goal with 2.0 should be to identify the <em>essential</em> use cases for each component, and what <em>specific</em> problems need to be solved. Components should be designed in such a way as to allow injection of alternate implementations, either through extension or implementation of interfaces. Any additional use cases can be covered either in alternate implementations shipped in the framework, or in custom, userland implementations outside the framework. The focus on maintenance should be on the core functionality of the component (and framework), no more, no less.</p>

<p>Additionally, we should examine components carefully to determine if a need for the component still exists, and whether the component is still under active maintenance. If the answer to either question is "no," we should consider removing the component.</p>

<h4>Make Code Readable</h4>

<p>One of the "rules" of Zend Framework 1.X development was that all code should have vendor and component prefixes. In fact, a 1:1 relationship between the classname and the filename has been enforced. This is a good practice overall, but with the use of "vendor prefixes", it has led to some verbose and difficult to read code.</p>

<p>For instance, to refer to any given class name, you must use the full classname. While this is not problematic for top-level classes such as <code>Zend_Loader</code> and <code>Zend_Registry</code>, once you get much deeper, the classes become unwieldy, and the prefixes tend to distract from the actual function of the given class: e.g., <code>Zend_Controller_Action_HelperBroker</code> seems like overkill for a class that is simply a "Broker". </p>

<p>Additionally, this leads to over-long lines. If I need to reference more than one classname in a given line, I'm almost guaranteed to exceed the recommended line length and/or split the line into multiple lines. This leads to reduced comprehension for those trying to read and understand the code. Class names, method names, and variable names should be brief. Namespaces in PHP 5.3 can help make this a reality for classnames.</p>

<p>Finally, there is inconsistency in the framework with how code is formatted. While we have a published Coding Standard, we do not always follow it. Additionally, some practices are considered "optimal", but not "required" – practices such as alignment of operators, keeping variable names meaningful yet short, consistent indentation, etc. For some detailed examples and discussions of why, read <a href="http://www.perforce.com/perforce/papers/prettycode.html">the Seven Pillars of Pretty Code</a>. These details need to be made required, and enforced via peer code reviews or pre- and/or post- commit hooks utilizing a utility such as <code>PHP_CodeSniffer</code>.</p>

<h4>Identify Common APIs</h4>

<p>Within the framework, we have a variety of common practices that have slight variations. As examples:</p>

<ul>
<li>Both action controllers and views can make use of "helpers" – but the mechanisms of how these work differ (action controllers use a "broker"; view objects call on helpers via method overloading).</li>
<li>View objects allow post-filtering of rendered contents – but the filters themselves do not follow the same interface as those found within the Filter component.</li>
</ul>

<p>Having differences between APIs makes learning the framework more difficult. We must identify those areas that are functionally similar, and refactor them to use the same common basis. This will ensure consistency across the framework, which will make learning and mastering the framework easier.</p>

<h4>Goals</h4>
<ul>
<li><strong>MUST</strong> remove obsolete, deprecated, or unmaintained components</li>
<li><strong>MUST</strong> rely on PHPUnit features to automate and simplify test suite maintenance
<ul>
<li>
<ul>
<li>data providers</li>
<li>@group annotations</li>
<li>setExpectedException()</li>
<li><code>TestAsset</code> namespaces</li>
<li>etc.</li>
</ul>
</li>
</ul>
</li>
<li><strong>MUST</strong> make code more consistent
<ul>
<li>Consistency in naming conventions
<ul>
<li>Classes are nouns, methods are verbs</li>
<li>Interfaces are nound or adverbs</li>
<li>Abstract classes are predictably named</li>
<li>Interfaces for any component that could have multiple strategies</li>
</ul>
</li>
<li><strong>MUST</strong> establish well-defined guidelines regarding code formatting to enforce readable code
<ul>
<li><strong>MUST</strong> migrate code to use namespaces</li>
<li><strong>MUST</strong> utilize a code sniffer, and define rules that correspond to our coding standards</li>
</ul>
</li>
<li><strong>MUST</strong> define and enforce consistent APIs; as examples:
<ul>
<li>Plugins</li>
<li>Adapters</li>
<li>Strategies</li>
<li>Helpers</li>
<li>Leverage language features when possible to assist (__invoke(), closures, etc)</li>
</ul>
</li>
</ul>
</li>
</ul>

<h3>Programming by Contract</h3>

<p><a href="http://en.wikipedia.org/wiki/Design_by_contract">Programming by Contract</a> asks<br />
developers and architects to create solid interfaces and answer the following<br />
questions during development:</p>

<ul>
<li>What does it expect?</li>
<li>What does it guarantee?</li>
<li>What does it maintain?</li>
</ul>

<p>(bullet points copied verbatim from the <a href="http://en.wikipedia.org/wiki/Design_by_contract">wikipedia article</a>)</p>

<p>Basically, any time an object uses collaborators, we should be defining<br />
interfaces to allow developers to inject their own implementations. These<br />
interfaces must be well-designed to ensure that we accurately capture the<br />
requirements of collaborators.</p>

<p>As an example, in the 1.X series of <code>Zend_Controller</code>, we have abstract <code>Request</code> and <code>Response</code> objects. These have grown over time to include additional functionality useful to developers, but the core functionality used within the ZF components themselves is quite minimal. Ideally, we would create lean interfaces capturing the behavior necessary for <code>Request</code> and <code>Response</code> objects to work in the ZF MVC – thus making it easier for developers to slip-stream in their own implementations. Any functionality beyond what is defined in the interface would be relegated to individual implementations, and likely through collaborator objects to ensure that alternate implementations don't break additional functionality.</p>

<h4>Goals</h4>

<ul>
<li><strong>SHOULD</strong> adhere to <a href="http://en.wikipedia.org/wiki/Solid_(object-oriented_design)">SOLID principles</a>.</li>
<li>All components <strong>MUST</strong> allow for dependency injection.</li>
<li>When collaborators are defined for a component, collaborators <strong>SHOULD</strong> follow a defined interface; if an interface does not exist, one <strong>SHOULD</strong> be defined.</li>
<li><strong>COULD</strong> implement a Dependency Injection container or utilize one from a third party source (such as Symfony Components).</li>
</ul>

<h3>Favoring the Explicit</h3>

<p>One obstacle new ZF developers face is identifying the source of functionality within the framework. One prime example is view helpers. As an illustration, consider the following example code from a view script:</p>

<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
<?php echo $this->headStyle(); ?>
]]></ac:plain-text-body></ac:macro>

<p>Developers using an IDE can determine quickly that <code>$this</code> refers to the view object, but, unfortunately, most IDEs cannot determine the source of the function <code>headStyle()</code> – because it does not exist in the view object. The new developer may then turn to the API documentation – and fail to locate the method. If they're familiar with the concept of overloading, they may look at the <code>__call()</code> method finally, and discover that it proxies to view helper objects, but then they need to determine how view helpers are loaded and executed. All-in-all, it adds a ton of overhead when trying to learn the framework.</p>

<p>Additionally, "magic" methods such as <code>_<em>call()</em></code><em>, </em><code><em>get()</em></code><em>, and </em><code>_set()</code> have performance implications; they take roughly 6x longer to execute than simply calling a standard method. By favoring explicit calls, we can likely radically improve the baseline performance of the framework.</p>

<p>In the above example of view helpers, how might we change the design to be more explicit? One potential solution would be to introduce a "helper broker", and use it to access helpers. Some use cases might look like this:</p>

<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
$view->broker()->attach('greeting', new MessageHelper());

// Proxy execution through the broker
echo $view->broker()->execute('message', 'world');

// Execution of an interface method on a helper pulled from the broker
echo $view->broker('message')->execute('world');

// Execution of an arbitrary method on a helper pulled from the broker
echo $view->broker('message')->greeting('world');

// Retrieving a helper from the broker, and acting on it
$helper = $view->broker('message');
echo $helper->execute('world');
echo $helper->greeting('world');
echo $helper('world'); // using __invoke()
]]></ac:plain-text-body></ac:macro>

<p>In all such cases the user can easily traverse the API and also get assistance from the IDE; all calls (except the last example, using invocation) use explicit methods, with clearly-defined return values. </p>

<p>This explicit approach is slightly more verbose than using the magic methods, but should ensure that code is simpler to understand, more consistent to use, and more easily maintained.</p>

<h4>Goals</h4>
<ul>
<li>Evaluate all uses of <code>__magic_method()</code> calls, and determine if they may be refactored to remove them.</li>
<li>Where we determine magic methods are necessary, their usage should be well-documented</li>
</ul>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. May 27, 2010

    <p>Glad to see these requirements for ZF2! Can't wait to test the first implementations.</p>

    <p>Concerning the Dependency Injection Container, I have worked a lot on integrating the Symfony DI Container with ZF. I have integrated it into Zend_Application and into the dispatcher to let the container manage the controllers lifecycle and their dependencies. I have also developed an annotation loader for Symfony DI Container to allow service definition by annotation.</p>

    <p>I ended with a really solid, highly configurable, decoupled, flexible, evolutive and testable multi-layered PHP architecture that I use in my professional and personal projects. I have also developed a Doctrine 2 integration into ZF and this multi-layered architecture with generic service and scaffolding (for forms, services, controllers and views): it works very well! You can check my code on my GitHub: <a class="external-link" href="http://github.com/loicfrering/losolib">http://github.com/loicfrering/losolib</a>.</p>

    <p>Here is an example of what I can achieve with the DI Container:</p>

    <ac:macro ac:name="code"><ac:default-parameter>yaml</ac:default-parameter><ac:plain-text-body><![CDATA[
    parameters:
    auth.adapter.entityName: Application_Model_User
    auth.adapter.identityField: email
    auth.adapter.credentialField: password

    services:
    auth.adapter:
    class: LoSo_Zend_Auth_Adapter_Doctrine2
    arguments: [@em, %auth.adapter.entityName%, %auth.adapter.identityField%, %auth.adapter.credentialField%]
    auth:
    class: Zend_Auth
    constructor: getInstance
    ]]></ac:plain-text-body></ac:macro>

    <ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
    <?php
    /**

    • @Service
      */
      class Application_Service_AuthService
      {
      /**
    • @var Zend_Auth
    • @Inject auth
      */
      protected $auth;

    public function setAuth($auth)

    Unknown macro: { $this->auth= $auth; return $this; }

    /**

    • @var Application_Service_Doctrine_UserService
    • @Inject
      */
      protected $userService;

    public function setUserService($userService)

    Unknown macro: { $this->userService = $userService; return $this; }

    /**

    • @var Zend_Auth_Adapter_Interface
    • @Inject auth.adapter
      */
      protected $authAdapter;

    public function setAuthAdapter($authAdapter)

    Unknown macro: { $this->authAdapter = $authAdapter; return $this; }

    protected $user;

    public function authenticate($username, $password)

    Unknown macro: { $this->authAdapter->setIdentity($username) ->setCredential($password); return $this->auth->authenticate($this->authAdapter); }

    public function hasIdentity()

    Unknown macro: { return $this->auth->hasIdentity(); }

    public function getIdentity()

    Unknown macro: { return $this->auth->getIdentity(); }

    public function getIdentityAsUser()
    {
    if (null === $this->user)

    Unknown macro: { $this->user = $this->userService->findOneByEmail($this->getIdentity()); }

    return $this->user;
    }

    public function isIdentifiedUser($user)

    Unknown macro: { return $user->getEmail() == $this->getIdentity(); }

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

    <p>To conclude I think that a DI container is really pertinent to PHP and ZF and I'd love to see one in ZF2.</p>

    <p>I'll be happy to debate about the community interest for a DI container in ZF and ZF Core team thoughts on integrating a DI container into ZF2.</p>

  2. May 28, 2010

    <p>"To conclude I think that a DI container is really pertinent to PHP and ZF and I'd love to see one in ZF2." </p>

    <p>You bet!</p>

    <p>+ Service-Layer usage (softly) forced by default-application-layout and abstract fwk classes & interfaces to make life easier and services more standardized<br />
    + Annotation-based dependency injection in controllers (services, models, helpers)</p>

    <p>Cheers,<br />
    Michael</p>

  3. May 31, 2010

    <p>Even though it's stated that the contributors are very few and the first mentioned goal is to "Ease the learning curve", I interpret this document as an active step towards more rules and angles to get caught in. What is the strategy to learn ZF more easily? I don't think another quick start will get us very far.</p>

    <p>What I do think would help:</p>

    <p>Get people to framework.zend.com: have a forum which helps people gather around instead of spreading them out, hire the guy of zendcasts.com, build a serious version of zfsnippets.com with unit tests, host more slides (slideshare is a goldmine, so's the official webinars but oh so few) - in short, a little bit more of web 2.0's social side. There's so much good stuff in personal blogs out there that risks never being found in time, possible nail on the head: Matthew Weier O'Phinney's blog - much more involvement from users than on the official devzone (possibly a bad comparison but you get my point), and also often a really relevant source for day-to-day use.</p>

    <p>Key point: ZF strongest point is the quality of its code, let it stay that way but a team of 10 people doing QA/contributing to the ideas of 1000's would make the project go way faster forward.</p>

    <p>— switching mode</p>

    <p>(Small standards) I'd like to see in ZF2:</p>
    <ul class="alternate">
    <li>make all strings constants instead, for code completion, phpdoc and typo-freeness (would break on failure). Zend_Date is ace.</li>
    <li>include faulty arguments together with each exception thrown</li>
    </ul>

    <p>Cheers from an happy end user who wants to find more time fiddling with ZF and less time googling.</p>

    1. Jun 07, 2010

      <blockquote>
      <p>make all strings constants instead</p></blockquote>
      <p> I 100% agree.  I much prefer to see constants used instead of a generic string even if the string itself is very descriptive.<br class="atl-forced-newline" /></p>

      <p>This may be debatable, but I actually find the current "Favoring the Explicit" section somewhat hypocritical.  All of the calls are just arbitrarily named strings.  I would have preferred to have seen almost all of those strings be replaced with a constant that were <strong><em>explicitly</em></strong> associated with the method/object it was called on/from (basic example):<br class="atl-forced-newline" /></p>

      <p>$view->broker()->attach('greeting', new MessageHelper());</p>

      <p>echo $view->broker()->execute(MessageHelper::message, 'world');  </p>

      1. Jul 27, 2010

        <p>The keys need to be managed, you can't have multiple helpers with the same key. This makes it cumbersome to use integer values. String values are a little easier to keep track of as human beings, but what is preventing you from using the string value? A string is a constant, just not a class constant.</p>

        <p>Another thing one might consider is keys generated by the broker. The problem with that approach is that you no longer know what key references what helper, unless you keep a reference, in which case you might as well keep a reference to the helper object, and avoid keys all together.</p>

        <p>The last option I can think of is a static key that isn't user devised and unique for each class. Say, the (full) class name?</p>

        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        public static function getName(){
        return _class_;
        }
        ]]></ac:plain-text-body></ac:macro>

        <p>I don't like the "execute" method, as that would require call_user_func, I'd rather have a little train wreck:</p>
        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        use some\name\space\MessageHelper;

        echo $view->broker()>get(MessageHelper::getName())>world();
        ]]></ac:plain-text-body></ac:macro>
        <p>As an added bonus, the use statement makes it clear which helper you're actually using.</p>

        <p>Of course the view can delegate to the broker making it shorter and more explicit:</p>
        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        use some\name\space\MessageHelper;

        echo $view->getHelper(MessageHelper::getName())->world();
        ]]></ac:plain-text-body></ac:macro>
        <p>Attaching is easier, because the key is static:</p>
        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        $view->attachHelper(new MessageHelper());
        ]]></ac:plain-text-body></ac:macro>
        <p>Mocking is easy as well:</p>
        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        use some\name\space\MessageHelper;

        $view->attachHelper($this->getMock(MessageHelper::getName()));
        ]]></ac:plain-text-body></ac:macro>
        <p>This of course only works with stateless helpers, but that's the whole point: if the helpers were stateful, we wouldn't want a reference to the same object, we'd construct a new one.</p>

    2. Jul 27, 2010

      <p>Zend_Date is ace? Zend_Date is fundamentally flawed: it should be a value object.</p>

      <p>EDIT: Btw, where do I complain about Zend_Date not being a Value Object?</p>

      1. Sep 26, 2010

        <p>You took that out of context. I would agree with you that Zend\Date should be a value object, but the use of constants in Zend\Date is suitable imo.</p>

  4. Jun 04, 2010

    <p>I personally believe the best way to ease the learning curve is to improve documentation. The current documentation is good, but sometimes inconsistent in quality and needs to be improved to help inexperienced developers to learn the framework. You should consider hiring a UI / UX expert to redesign the manual and some technical writers to rewrite some parts of the documentation that are lacking. Either that, or assign the better writers among the team to write the documentation.</p>

    <p>Of particular note is the quickstart guide, which while an improvement on having no such guide is not ideal as it is. It targets linux system specifically while leaving small notes for other systems which are not very helpful unless you understand exactly what is expected. The entire part on vhost is confusing to most new developers, and is completely unnecessary as you can run multiple Zend Framework projects from different directories on the same (default) document root - which should be the simplest method for inexperienced developers (especially for the development machine or shared hosting).</p>

    <p>I've been a happy user since version 0.2, and I'm really glad that Zend is supporting the framework into its next evolution. Hopefully, the internals won't change as much as to require learning it completely from scratch.</p>

    1. Jun 17, 2010

      <p>Regarding your assertion that setting up a vhost is "...unnecessary as you can run multiple Zend Framework projects from different directories on the same (default) document root," this is, and has been, an explicit decision we've made since the very beginning. While it <em>is</em> possible to do as you mention, and it may be the simpler way to do so, the fact of the matter is that we <em>don't</em> do so as a matter of good programming practices. Dropping the entire application into your document root is a recipe for disaster – there are countless anecdotes across the web showing cases where PHP source code in the document root has been served as plain text and/or exploited. By pushing it <em>out</em> of the document root, we provide a more secure methodology from the outset.</p>

  5. Jun 04, 2010

    <p>On the contrary, I must say documentation is quite poor generally. Even if you take a look to the API docs, most of the parameters aren't properly explained; or you never know if you need to pass a string, an array or what until you examine the corresponding piece of code and even then it's often difficult to know what to do...</p>

  6. Jun 08, 2010

    <p>I don't think removing the use of php's magic functions would add to readability in all cases. Especially in view scripts, which are sometimes written by non-technicals, we should focus on keeping the code as simple as possible.</p>

    <p>ZF had been accused of being "java-ish" in the past, why add additional complexity (if only at first glance)?</p>

    1. Jun 17, 2010

      <p>Using __call() has a number of disadvantages from the outset:</p>

      <ul>
      <li>For newcomers to the framework, I have seen many questions asking, "where did this method come from?" While you argue it's more readable to use __call(), for these developers, they do not know where to find the documentation for those "methods" in the API.</li>
      <li>__call() also has performance implications. In this case, you first get trapped by __call(), then it needs to locate a helper class, instantiate it, and then use call_user_func_array(). __call() by itself is roughly 6x slower than a normal function call; call_user_func_array() is quite expensive as well. By using an explicit broker, we can actually eliminate the most expensive parts of the code entirely.</li>
      <li>Re-usability suffers. Many developers want to use alternate rendering engines, but still like the view helpers that currently exist. However, since the broker mechanism is built into Zend_View, they either have to copy/paste that functionality, build their own, or omit it. Using an explicit broker makes that functionality more re-usable.</li>
      </ul>

      <p>I agree that we shouldn't remove magic functions in all cases – but we need to make analysis like I've done above to see what issues using them causes.</p>

  7. Jun 08, 2010

    <ac:macro ac:name="unmigrated-wiki-markup"><ac:plain-text-body><![CDATA[As Carlos mentions it can be difficult to know what available values $options may take without looking more closely at the code - this especially true when working with the Zend_Form.

    Change is sometimes hard to adjust to, but I hope that the magic calls are not completely removed. Doing so will make the user code more dense. The lighter the code syntax the better it is to work with.

    One problem I've had with the IDE's and code completion is that this doesn't work when using a factory type method is used whether it be the magic method __call or a broker method. So for me the alternative was to create hard methods for the common usages - this I think would be beneficial for some of the more frequent helper/broker controller/view methods and as measure of optimization.

    One trick I've seen for minimizing the cost of call_user_func_array is to count the number of args and have explicit calls supporting up to three args, eg.

    if ($count == 1) {
    $obj->$method($arg[0]);
    } else if ($count == 2) {
    $obj->$method($arg[0], $arg[1]);
    }

    Something that I've yet to see is a decent way to handle view variable assignments from within the controllers. There are times when a view/script may need more variables than what the controller only needs to work with yet before rendering the script it must also assign a bunch of others - this makes it either ugly or confusing as to how best to then render the view script and either further confusing when also assigning layout view variables - helpers doesn't quite seem the best way of resolving this in all cases. It might be good if some kind of pre-render method was called?

    With the right optimizations and I think ZF can perform within reasonable bounds, hopefully the changes planned will not completely lose some of the beauty of the ZF code literally for the sake of performance - a balance and or at alternative could be made, e.g those who know and are overly concerned would create real methods as appropriate as opposed to the _call/get/_set function etc.]]></ac:plain-text-body></ac:macro>

    1. Jun 17, 2010

      <p>Regarding the "count" trick you mention, I've seen it myself. It works fairly well, so long as you know the method you will call already. If the method is unknown, then in PHP 5.3, it's basically just as fast, if not faster, to simply use call_user_func_array().</p>

      <p>Regarding your points about IDEs, it's one more rationale for using a broker system, as you get code completion in IDEs and editors that support it; it also eliminates the __call()/call_user_func_array() bottlenecks:</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      echo $broker->get('helper')->someMethod($arg1, $arg2);
      ]]></ac:plain-text-body></ac:macro>
      <p>This doesn't completely solve the code-assist problem – you still have short names – but you're now no longer using __call() or call_user_func_array(), which are the largest bottlenecks in terms of performance. It's also more explicit – you're calling methods on your helper objects themselves. The syntax is less compact, but there are ways around that: assigning helpers to the view or to variables inside the view achieve this.</p>

  8. Jun 10, 2010

    <p>The obsession with testability at the expense of simplicity and consistency is frustrating. Usually helpers don't maintain state and are an ideal case for static methods. To call a method like this is insanity:</p>

    <p> $view->broker()->execute('message', 'world');</p>

    <p>when there is a standard simple equivalent:</p>

    <p> Message::world();</p>

    1. Jun 11, 2010

      <p>The obsession with simplicity is frustrating. Usually helpers maintain state across mutiple calls and are not an ideal case for static methods. The call a method like this is insanity:</p>

      <p>Message::world();</p>

      <p>Because now I can't even mock out it's existence and have to resort to kludgy static invokation overriding in PHP 5.3...ugh. Especially when there is a simpler way I can properly test with:</p>

      <p>$view->broker()->execute('message', 'world');</p>

      <p>Off the sarcasm trip, it can be frustrating in both directions <ac:emoticon ac:name="wink" />.</p>

      1. Jun 11, 2010

        <p>So is this a framework for a fringe group of unit testers? If so, then let's be honest about that. Starting with removing the words "Extreme Simplicity & Productivity" from the ZF overview page. </p>

        1. Jun 12, 2010

          <p>Unit testing is one of the more essential requirements in professional development today. It's not a "fringe" practice at all and I am clueless as to where you got that idea. So whether you agree with it or not, the framework allows for testable code. Statics will be used where necessary, but will NOT become commonly required within the framework.</p>

          1. Jun 14, 2010

            <p>Undeniably, most web applications aren't unit tested. So yes, fringe is an accurate statement.</p>

            <p>Regardless, sacrificing good software design, the most important characteristic of which is simplicity, to appease unit testers is madness. These complexities don't mesh with the MIT or "Worse is better" sensible approahes to design. I won't convince you of this, but this framework has a reputation that won't improve until the academics stop their fiddling. </p>

        2. Jun 17, 2010

          <p>Sure, let's drop unit testing from Zend Framework. And in six months, I'll ask you again if you think it's a fringe requirement. At that time, we can remove the "& Productivity" from the overview, because without a tested codebase, we won't be able to maintain it, and <em>you</em> won't be able to be productive with it anymore due to the bugs.</p>

          <p>Look, we're not asking you, an end-user, to unit test your application. However, you, as an end-user, are asking us to give you quality code that you can depend on. The only way we can do that is to test it, and writing code that is testable in the first place makes this job easier for ourselves, as well as the other dozens of developers that may assist us.</p>

          <p>We also have a responsibility to end users: they should be able to test their code easily, as well as be able to inject their own dependencies at will. Statics are a poor solution for this. I can't tell you how many times I thought statics were the right solution... only to end up with a ton of code duplication and hacks when I wanted to extend or re-use them.</p>

          <p>Regarding your later post, you make the assertion that testable code "sacrifices" good software design. I'd argue the opposite. <em>Writing testable code often helps expose bad APIs.</em> Additionally, when doing test driven development, you give yourself a chance to play with the API before coding it, giving yourself a chance to ask whether it's one you'd actually want to use. I did this with the rewrite of Zend\Session, and I scratched my initial designs as they were too complex to use; the final version ended up fairly simple for use... and also testable.</p>

          <p>You may consider unit testing fringe. I, and many others, consider it essential for ensuring code quality. You're welcome to disagree.</p>

        3. Jul 27, 2010

          <p>It's also about good practice. If you add static operations, it's too easy to call those operations from places where you shouldn't. With a non-static interface, you have control over access to the procedure in the layers between. Especially in a project with multiple developers, this is a must. You might not like someone calling a view helper in your business object, for example. Yes, he could construct the helper, assuming there are no initialization dependencies. Say a view helper that renders a sitemap, gets the site tree injected. If the helper procedure is static, that dependency is as well. Long story short, you're making abuse very easy. The difference to functions and globals is marginal. You know, the olden, procedural days. When everything PHP was complete and utter crap, even if we didn't know it. <ac:emoticon ac:name="wink" /></p>

  9. Jul 04, 2010

    <p>With all due respect, I'd point out this issue <a class="external-link" href="http://zendframework.com/issues/browse/ZF-5734">http://zendframework.com/issues/browse/ZF-5734</a> which, besides being wrong on its own, makes almost impossible to create some rational application structures.</p>

    1. Jul 04, 2010

      <p>Please see my comments on that issue. Basically, it's not "wrong" – there were reasons we did not implement such functionality, and won't be doing so anytime soon. However, by having strong (and hopefully simple) interfaces, we can make it possible for userland implementations that have those requirements.</p>

      1. Jul 05, 2010

        <p>I see, thanks for your comment to which I replied there. Maybe we should discuss it here, shouldn't we?</p>

        1. Sep 27, 2010

          <p>No, it should be discussed when we start creating proposals for the MVC milestone. <ac:emoticon ac:name="smile" /></p>

  10. Oct 03, 2010

    <p>Just came across a beautifully done presentation on another frameworks large update. Something like this <a class="external-link" href="http://rubyonrails.org/screencasts/rails3/getting-started-action-dispatch">http://rubyonrails.org/screencasts/rails3/getting-started-action-dispatch</a> would help out a lot with the launch of 2.0.</p>

  11. Nov 20, 2010

    <p>What frustrates me is:</p>

    <p>1) The morass of file paths and file hunting to load them which I suspect is expensive.<br />
    2) "Use at will" seems to be degrading where "instanceof" tests on an abstract instead of an interface<br />
    3) Zend_Application seems to have added another layer of load (should be lazy instantiation - always)<br />
    4) The MVC isn't fast enough to provide image serving (a lot more requests). I think it should be.<br />
    5) Remove all regular expressions unless really needed, because they're expensive too.</p>

    <p>Make the cache the first resource to get, so even the config itself is cached unwrapped as an array. Cut right down on checking for files/modules everywhere. Test for files once then record it all in memory cache and don't test again.</p>

    <p>The whole front-end needs to be super fast. Do not load anything until it is required. Cut out as much plugin/helper searching as possible. I ditched the dir layout and made it a dir of App, MyLib, Zend, where App looks like a library itself except for the non-class files it contains so most classes come straight off the include path. If people need to load stuff outside if this convention then I think it should be a hook to custom load before failure.</p>

    <p>Ditch the no-module dir layout entirely. Make modules discrete units declaring dependent modules.</p>

    <p>I have rolled my own-front end to do these things and it is very fast, but admittedly my hack and I'm suffering because it exposes how much use-at-will in the Zend library seems to have degraded.</p>

    1. Nov 20, 2010

      <p>I appreciate your frustration. I invite you to look at what is happening currently in the ZF2 repository, as we're addressing much of what you discuss in this comment already.</p>

      <p>1) Not completely sure what you mean by "morass of file paths", but I suspect this may have to do with two separate issues: (a) application resources do not follow the same rules as library autoloading, leading to many stat calls, and (b) plugin loading uses many stat calls. (b) is already addressed in the ZF2 master branch. (a) will be resolved as we work on the MVC milestone.<br />
      2) One of the driving goals of ZF2 is to have strong interfaces, and only typehint on interfaces.<br />
      3) Zend_Application's primary performance issue is due to plugin loading - something already solved in ZF2 master. That said, it has additional issues – no clear way to load resources only as needed by a specific request, no caching of configuration (as you note later), etc. Those are all items we're looking at in the MVC milestone.<br />
      4) I agree on this point. The goal of the ZF2 MVC will be to return a response as quickly as possible, and mechanisms for returning that response as soon as it is ready.<br />
      5) Give me benchmarks showing regular expressions are slow. Hint: you can't. Modern versions of the PCRE library are blazing fast, and our own profiling has shown that regexp are the least of our worries with regards to performance. A well-formed regex can perform much faster than a series of string-related functions.</p>

      <p>While I understand your request about ditching the "no-module" directory layout, I'll note that the include_path is the wrong reason to do so. Autoloading based on the include_path is simply bad from a performance perspective (something I've blogged on as part of my research for alternate autoloading solutions for ZF2). There are better reasons to do so: consistency between application and library code, consistency. That said, we also want to make the migration path for ZF1 users as easy as possible, so we'll likely need to ensure current application structures continue to work.</p>

      <p>Over all, however, I think you'll find that most performance concerns have been addressed in the current ZF2 master branch. Some work still needs to be done – Zend_Form still needs to be refactored to use the new plugin broker mechanisms – but the improvements are quite dramatic already.</p>

      1. Nov 21, 2010

        <p>Regarding Mark's comment of ditching the no-module directory layout, I think I can agree. While I understand migration issues are a concern for some, isn't ZF2 a backward compatibility break? If a more flexible, modular application structure is to be desired, supporting the standard application structure of ZF1 will add additional complexity to MVC code.</p>

        <p>As flexibility is concerned, one can look at Magento's modular architecture. I've been developing with Magento for the past few months, and while it is notorious for code smells, it has a fairly flexible modular layout. For ZF2, I think most of us would like to see modules be first-class citizens. Rather than have an application namespace starting with the application directory, and plural directories (forms, resources, controllers, plugins, models, etc...), why not have source folders and namespaces? For example, to achieve flexibility that would trump Magento, we could have a directory structure like the following:</p>

        <p>apllication/configs/application.ini<br />
        apllication/src/<namespace>/<module>/Controller/Index.php<br />
        apllication/src/<namespace>/<module>/Model/<model classes><br />
        apllication/src/<namespace>/<module>/<other module sub-categories><br />
        apllication/Bootstrap.php</p>

        <p>My idea for namespaced modules is inspired by Magento. With the above structure, we could have a default application namespace and module defined in application.ini. Additionally, adding the ability to "rewrite" or overload an existing module's class. For example, lets imagine I have an application whose default namespace and module are as follows:</p>

        <p>apllication/src/Application/Base/</p>

        <p>The base module of the Application namespace contains the typical sub categories, such as Model, Controller, etc... If I want my application to be extensible, like Magento, implementing developers should be able to override/extend the Base module classes as needed. So let's say I'm a developer and want to extend an existing Base module controller. I would add my own namespace and module:</p>

        <p>apllication/src/Joly/Base/</p>

        <p>In application.ini (or better yet, a module specific config file), a controller rewrite configuration will need to be specified. So something like </p>

        <p>resource.frontController.rewrite.Application.Base.Controller.Index = "\Joly\Base\Controller\Index"</p>

        <p>Or perhaps a better place to specify rewrites would be in a single rewrite node specifying all classes being overridden:</p>

        <p>rewrite.Application.Base.Controller.Index = "\Joly\Base\Controller\Index"</p>

        <p>When the autoloaders are initialized, the "Joly" namespaced class would replace the "Application" class.</p>

        <p>I have an open source CMS I will be working on soon and need it to be a very flexible, modular application, and the current MVC isn't of much use to me. The notes regarding the MVC milestone are encouraging, as the issue regarding modules being "tacked on" is clearly stated. On a side note, I have not noticed any proposals for the ZF 2 MVC components yet. I could put together a proposal for this myself if there aren't any proposals currently in the works.</p>

      2. Nov 23, 2010

        <p>Matthew. Replying to the 5 points earlier. I've seen your blog article now and looked at the ZF2 snapshot now too - thanks.</p>

        <p>1) Yes, stat calls and file searching/testing. Also, I had no idea that the include path is sub-optimal. File loading performance solved with ZF2 then hopefully.</p>

        <p>My use of "morass" was more about the apparent complexity and variants in the manual on dir layouts and then also what the library code itself defaulted to. I just find myself spending time trying to work out where a file goes in order to get it picked up by default and when that fails end up wrestling with the loader configs.</p>

        <p>The manual recommends this:
        <a class="external-link" href="http://framework.zend.com/manual/en/project-structure.project.html">http://framework.zend.com/manual/en/project-structure.project.html</a><br />
        but then we see this:
        <a class="external-link" href="http://framework.zend.com/manual/en/zend.controller.modular.html">http://framework.zend.com/manual/en/zend.controller.modular.html</a></p>

        <p>If the manual gave full path examples based on one, and only one dir layout and ZF had corresponding defaults for all locations I think ZF would feel a lot quicker to work with. Perhaps longer term the new tooling will become the way to grow every aspect of the app, with a verbose option so you can see where all the files have been created.</p>

        <p>2) Interfaces. Could there be a hard rule that between-component object communication must be by interface? So reducing this list somewhat: grep -r Abstract library | grep instanceof | less</p>

        <p>3) I get the impression that ease of migration is a strong consideration despite the BC break opportunity, so perhaps we're stuck with Zend_Application. In my MVC I just did away with it and provided resource loading in the front controller assisted by resource bootstraps to call hasResource/getResource again for dependencies. All cached, lazy loaded, just a few methods to do it. Zend_Application seems like bloat to me.</p>

        <p>4) Encouraging. I suppose in production I can at least concatenate the classes required in every request into a single file if need be.</p>

        <p>5) Regular expressions. Years ago I won a sporting bet with a colleague over this and that formed my view. You say it's been optimised. I'll take your word for it and agree it's nothing compared to disk or db access time costs. Not worth trifling over.</p>

        1. Nov 23, 2010

          <p>Responding to the individual points...</p>

          <p>1) This is a case where some docs have gone out of date without being updated. The zend.controller.modular docs are out-of-date, and should likely be removed or revised at this time. The project-structure docs are current, and reflect how Zend_Tool will create a project.</p>

          <p>2) Using interfaces does not necessarily mean eliminating instanceof checks. It's often most flexible to allow passing either an object <strong>or</strong> a class name representing an object. This leads to instanceof checks in the code body, as we have to then eliminate the type hinting in the method signature. What's more important is that we program <em>to</em> the interfaces, and don't call methods defined in the concrete classes that are not part of those interfaces.</p>

          <p>3) One thing we're looking at with Zend\Application in 2.0 is having the container extend PluginSpecBroker, and then no longer bootstrapping all resources. This allows the application to pull resources as needed – and only when pulled would they be instantiated. This will answer many performance issues, particularly in cases where you are only using a few resources out of your configuration.</p>

          <p>4) Absolutely. However, with a good opcode cache, class-map based autoloading will eliminate the need to do so, as they'll be cached in-memory after the first request.</p>

          <p>5) That <strong>was</strong> years ago. <ac:emoticon ac:name="smile" /> PCRE is <em>incredibly</em> fast, particularly when you're not doing crazy things like negative look-ahead/behind (and there are very few, if any places we do that in ZF). While most PHP string operations are faster, you often need to string together (pardon the pun) several such operations to achieve what you can do in a single regex – negating the performance benefit.</p>

          <p>Glad to see that current development is answering some of your questions already, and I look forward to your input when we open up the MVC milestone.</p>

  12. Nov 23, 2010

    <p>To the genearl goal "ease the learning curve":</p>

    <p>Many people write here, that writing more/better documentation, and more publishing of articles, slideshares and so on would improve the situation.<br />
    Sure, but is this the "main" goal?</p>

    <p>In my oppinion this is somehow the wrong approach!</p>

    <p>If the APIs of the components get consistent, many questions for ZF users are just eliminated with that. The classes are a big part of the "documentation", if they are clear, then you don't have to read a extra documentation in many cases.</p>

    <p>Sure you still need a good documentation, slideshares and so on, but even this would become easier.</p>

    1. Nov 24, 2010

      <p>During the "Introducing ZF 2.0" presentation I gave at ZendCon with Ralph, the "ease the learning curve" idea was a common thread throughout. As you note, it's not just documentation, but also making the code more consistent and simpler. (In fact, I actually specifically called out that the first step to easing the learning curve is code-based.) That said, the documentation <em>also</em> must be made more consistent, and more comprehensive, to ensure that those consistent APIs are readily apparent, as well as all their options and behaviors.</p>

  13. Dec 02, 2010

    <p>In the new ZF2 Loader component I notice mixed use of the leading underscore in private/protected declarations. Is this some emerging change in the coding standard?</p>

    <p>More generally, is the coding standard in ZF2 decided yet? Can I look it up?</p>

    1. Dec 03, 2010

      <p>We decided via online polls some months ago to:</p>

      <ul>
      <li>Remove the requirement for leading underscores on non-public members for new code</li>
      <li>Make a low-level, late milestone for removing underscores prior to the first beta</li>
      </ul>

      <p>We can't automate this completely as there are a number of places in the framework where we have underscore-prefixed methods where removal will now cause conflicts with existing methods.</p>

      <p>I plan to publish a revised ZF2 coding standard on the wiki in the coming weeks to reflect this and other changes we've made (typically on the zf-contributors list).</p>

      1. Dec 10, 2010

        <p>What drove the decision to remove underscores from private/protected methods and variables? Is there any logic behind this decision, or was it solely based on the results of online polls? In my personal dealings with Zend Framework, which I use consistently for most projects, I have found the underscores to be invaluable with regard to readability, and differentiation.</p>

        1. Dec 10, 2010

          <p>There was a ton of discussion on the topic on the zf-contributors list earlier this year, following which I opened a poll to the general public. The majority was in favor of removing them.</p>

          <p>While I could argue either side of the decision, the salient points are:</p>

          <ul>
          <li>In most the vast majority of class <em>properties</em>, we simply don't use "public" anyways – which means the underscore is largely irrelevant for them.</li>
          <li>Methods are the one place where having the leading underscore can help in differentiating method visibility during use. That said, API documentation and IDE hints (and yes, you <strong>can</strong> get reasonable hinting in text editors such as vim via a number of plugins) largely obviate the need for such differentiation.</li>
          <li>Changing visibility to public requires not just changing the visibility, but also removing the underscore, <em>and removing it in all calling code</em>. This is a poor situation at best, and one that completely goes away by dropping the underscore.</li>
          </ul>

          <p>After having written a number of components without the leading underscore at this point, I have to admit I favor its removal at this time, as it streamlines and simplifies the coding process, particularly when under rapid iterations.</p>

  14. Feb 02, 2011

    <p>Is dependency injection going to still require some kind of bootstrap file for every resource?</p>

    <p>If a unified constructor is not popular (re: comments on superceded ZF2 roadmap page), could it be ruled that ALL constructor arguments in ZF2 must be defaulted (null if necessary) to make them technically optional? So allowing instantiation as "new ResourceClass()" by default by the DI?</p>

    <p>If ZF2 got rid of all statically accessed singletons except one main singleton - a central app/kernel object (registries for all singletons, all App config, etc.), constructors could grab the kernel statically and interrogate it to work out dependent dynamic defaults. Or worst case, just instantiate in an initially unworkable state, pending an init()? This way you still have the constructor's type hinting showing what the object will need to work - so hopefully solving objections that the original unified constructor provoked.</p>

    <p>This allows the DI to just call "new ResourceClass()" and then if it also has some config to pass to it, follow up by then calling setOptions($config) on it, perhaps with a check on method_exists(), which on failure, throws a "No setOptions() method available. Configure by resource bootstrap instead" exception?</p>

    <p>If this, as a framework-wide rule was tolerable (and a script could easily ensure it was being observed), I'd have thought it would help automate config of non-resources too like auto-configuring complex forms and so on.</p>

  15. Feb 23, 2011

    <p>Any chance of moving from "getProperty()" naming to "property()" naming for getters?</p>

    <p>The getters are called most often and I think needlessly clutter code with "get" prefixed everywhere. property() seems adequate to me and clearly asking for a value. Not suggesting any change to setters (setProperty()).</p>

    <p>In my own code I've created a Scaffold abstract class to magically provide for setter/getters as above with legacy support for getProperty() style calls. So now I just declare private properties in a class extending Scaffold, all of which are magic-call-accessible until I'm ready to fill out explicit setProperty()/property() methods.</p>

    1. Feb 23, 2011

      <p>if we have set*() methods, I think it's just as clear to also have their get*() counterparts.</p>

      <p>Also, by prefixing it's automatically clear what a method does...</p>

    2. Feb 23, 2011

      <p>I don't understand your point of view. The getters are prefix often by <strong>get</strong> <ac:emoticon ac:name="smile" /><br />
      And, the <a href="http://framework.zend.com/manual/en/coding-standard.naming-conventions.html#coding-standard.naming-conventions.functions-and-methods">convention in ZF</a> is :</p>
      <blockquote>
      <p>For object-oriented programming, accessors for instance or static variables should always be prefixed with "get" or "set".</p></blockquote>

      1. Feb 23, 2011

        <p>Yes that is the convention.</p>

        <p>Sorry, I think I'd only be repeating my earlier post, other than to add that I just thought some other frameworks like Alloy look more readable without "get". First page of google results for "getters setters" influenced me too. Anyway, no biggy - it was just a thought.</p>

  16. May 16, 2011

    <p><em>If you don't know who you are, then you don't REALLY know where you're going, since you might then just be the guy over there walking the other way.</em> But seriously.. <ac:emoticon ac:name="smile" /></p>

    <p>What you're lacking here is a mission statement (or really.. a short identity tagline under the logo) that more definitively establishes what Zend Framework 2.0 is 'all about' in the PHP development ecosystem.. and, just as importantly, who the target developer (market) is.</p>

    <p>This is more pragmatic than it might initially sound as it can set reinforcing context and expectation for the kind of design decisions that have been, and are now, being made for v2.0.</p>

    <p>Since the PHP Developer community is vast and there's incredibly wide variance in developer skill, knowledge, and experience, it might be beneficial now to the ZF product brand (and focus!) to 'claim a little higher developer ground' amid the myriad PHP frameworks out there:</p>

    <p><strong>Zend Framework: Community-driven, enterprise-grade PHP Development Stack</strong> (or 'Web Library'.. or whatever)</p>

    <p>Given this, or something like this (I presume.. with something similar to the 'enterprise-grade' reference), it would then mean ZF 2.0's core mission is NOT really about 'Simplicity' nor catering to less experienced PHP developers or those less corporate-focused in their practices, code, and methodologies.</p>

    <p>I think this is actually the truth, but no one's really saying it (and there's definitely not a 1-line product 'mission' on THIS important page).. so you end up getting into mini 'Unit Testing' debates like the one in comments above)</p>

    <p>.. but with a SHORT EXPLICIT identity tagline/product motto including (I assume again.: an 'enterprise','corporate', or 'industrial' reference): </p>

    <p>*Unit-Testing? ... IN!<br />
    *Dependency Injection? . ABSOLUTELY!<br />
    *Doctrine 2 ORM support? .. MAKES SENSE!<br />
    *Community voting on core components & design? . NOT NECESSARILY, BUCKO!<br />
    *Follows BEST PRACTICES and STANDARD CONVENTIONS (when at all reasonable)? WELL, OF COURSE..it's the 'Enterprise-grade' framework!</p>

    <p>Just another 2 cents.</p>

  17. Nov 30, 2012

    <p><em>"Simply stated, Zend Framework 2.0 MUST be an exemplar of PHP 5.3 usage."</em></p>

    <p>The framework - specifically the EventManager - uses Traits that are supported from PHP version 5.4.0, according to the PHP docs (<a class="external-link" href="http://php.net/manual/en/language.oop5.traits.php">http://php.net/manual/en/language.oop5.traits.php</a>). How is that handled? Or is the PHP documentation in error?</p>