Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="note"><ac:parameter ac:name="title">Superceded</ac:parameter><ac:rich-text-body>
<p>This page has been superceded by <ac:link><ri:page ri:content-title="Zend Framework 2.0 Requirements" /></ac:link>; please direct further discussion to that page.</p></ac:rich-text-body></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 2.0 will be the first major version following the 1.x series, and as such is the first time BC breaks will be allowed. Our goal is to make breaks only where they make sense: <span style="text-decoration: line-through;">there will be no renaming of components just for naming consistency, but</span> we will improve the code base to make it more maintainable, easier to extend, or make use of new language features that better accomodate the design,</p>

<p>At this time, we aim to have ZF 2.0 have a minimum requirement of PHP 5.3 (which version of 5.3 is still to be determined). This allows us to make use of a number of new language features that better suit framework development, such as namespaces, __invoke(), closures, goto, Late Static Binding (LSB), etc.</p>

<p>This page serves to summarize various changes we will be making for 2.0, both as new features as well as improvements. Additionally, it links to several pages covering specific components.</p>

<h2>Architectural/Design Changes</h2>

<p>Our goal with ZF 2.0 is to improve the overall consistency of the project. With consistent APIs relating to constructors, options, and exceptions, developers can more readily grasp the basics of each component and move on to specifics of usage.</p>

<ul>
<li><strong>Unified constructor</strong>. All constructors will (optionally) accept an array of options or Zend_Config object as the first argument. This allows for more flexibility to add new arguments to the constructor, have variable numbers of arguments, and allow "named" arguments. Additionally, it's a good technique for allowing Dependency Injection.<br />
As part of this initiative, most components will also have a "setOptions()" method to which the options array will be passed (and which may be used later to reset object state). Typically, this will proxy to other setters.<br />
Many components in ZF 1.X already do this: Zend_Application, Zend_Form, Zend_Validate, Zend_Layout, etc. We are simply extending this paradigm to cover all components.<br />
In order to reduce code duplication, we will likely introduce a zend\Options class, which will work roughly as follows:
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
namespace zend;
class Options
{
public static function setOptions($object, array $options)
{
if (!is_object($object))

Unknown macro: { return; }

foreach ($options as $key => $value) {
$method = 'set' . self::_normalizeKey($key);
if (method_exists($object, $method))

Unknown macro: { $object->$method($value); }

}
}

public static function setConstructorOptions($object, $options)
{
if ($options instanceof Zend_Config)

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

if (is_array($options))

Unknown macro: { self}

}

protected static function _normalizeKey($key)

Unknown macro: { $option = str_replace('_', ' ', strtolower($key)); $option = str_replace(' ', '', ucwords($option)); return $option; }

}

use zend\Options as Options;
class Foo
{
public $bar = '';
public $baz = '';

public function __construct($options = null)

Unknown macro: { Options}

public function setOptions(array $options)

Unknown macro: { Options}

public function setBar($value)

Unknown macro: { $this->bar = $value; }

public function setBaz($value)

Unknown macro: { $this->baz = $value; }

}

$foo = new Foo(array('bar' => 'baz'));
echo $foo->bar; // "baz"

$foo->setOptions(array('bar' => 'boo', 'baz' => 'bat'));
echo $foo->bar . $foo->baz; // "boobat"
]]></ac:plain-text-body></ac:macro></li>
<li><strong>Options</strong>. In ZF 1.X, the various components which accept options accept a variety of formats: some expect underscore_separated keys, others expect camelCasedKeys, others expect UPPERCASEDKEYS, and some expect lowercasedkeys. This leads to confusion for many, and also leads to difficulties debugging. Our goal in ZF 2.0 is to standardize option keys to correct this situation.<br />
Currently, we are leaning towards all_lowercase_underscore_keys. These are human-readable, contain only valid PHP variable characters, and make for a simplified option parsing implementation. Additionally, it is trivial to translate such keys to camelCase ("str_replace(' ', '', ucwords(str_replace('_', ' ', $value)))") for purposes of overloading – and this makes it easy to document option key => class property affiliations.</li>
<li><strong>Exceptions</strong>. Each component will have an Exception marker interface, with exceptions defined for discrete exception types thrown by the component. The concrete exceptions will either extend the global Exception class or an SPL Exception, and also implement the component Exception interface. This allows us to throw appropriate SPL exceptions while retaining a common Exception type (via the marker interfaces). As an example:
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
namespace \Foo\Bar;
interface Exception
{
}

class InvalidArgumentException
extends \InvalidArgumentException
implements Exception
{
}

try {
throw new InvalidArgumentException();
} catch (\Foo\Bar\Exception $e) {
}
]]></ac:plain-text-body></ac:macro></li>
<li><strong>Design By Contract</strong>. We will be altering portions of the framework to follow the concept of <a href="http://en.wikipedia.org/wiki/Design_by_contract">design by contract</a>, and new development will follow this paradigm. At first, this will take the form of refactoring to add interfaces/refactoring interfaces to reflect actual usage.<br />
Interfaces make creating alternate implementations of standard classes easier, while assuring that these implementations will continue to work with the classes that consume them. In many cases currently, we offer only abstract classes, and no equivalent interfaces; in other cases, the consuming classes use methods that are not part of the interface.<br />
In addition to this initiative, we will be eliminating some functionality intended to add flexibility to some of the standard classes. We have found that oftentimes this functionality leads to performance overhead as well as consumes maintenance time that could be used better elsewhere in the framework. As an example, the Dispatcher has a number of methods for adding custom class -> file mappings that are largely unused and which use an unnecessary number of CPU cycles; refactoring this to follow only the standard use cases would ease maintenance, while having a good, simple interface would make creating alternate implementations for custom use cases easier.</li>
<li><strong>Elimination of most singletons</strong>. ZF has often been accused of "singletonitis." While we're not sure if we completely agree, we will note that in most cases, the singletons we have presented a number of problems and led to difficult test cases. Additionally, in most cases, the singleton is unwarranted. We will be refactoring to eliminate these, including in Zend_Controller_Front. In exceptional cases, we will keep them; these include global operations such as autoloading and database connections.</li>
<li><strong>Creation of components for general-purpose, cross-functional actions</strong>. A number of components duplicate code, and we want to push the duplication areas into discrete components that the original components may then consume. Some of these include:
<ul>
<li>Plugins/Helpers/Strategies (seen currently in Zend_Controller_Front, Zend_Controller_Action_Helper, Zend_View (helpers and filters), Zend_Form (validators, filters, and decorators), etc.). Plugin discovery and loading could benefit from a common API.</li>
<li>Decorators (seen currently in Zend_Form; other areas could benefit from the pattern)</li>
<li>Factories (seen currently in Zend_Db, Zend_Navigation_Page, Zend_Auth, Zend_Translate, Zend_Cache, etc.)</li>
<li>Caching (seen currently in Zend_Translate, Zend_Locale, Zend_Queue, Zend_Paginator, Zend_Feed_Reader, Zend_Db_Table, etc.)</li>
</ul>
</li>
<li><strong>Usage of new language features within plugin architectures</strong>. Currently, most plugins rely on the strategy pattern, but the mechanism differs between plugins. PHP 5.3 offers some compelling alternatives that we want to explore: __invoke() and closures. Closures are less compelling as we cannot do simple type-hinting on them. __invoke() offers perhaps the simplest solution, and could become a standard API for plugins.</li>
<li><strong>Autoload-only</strong>. We will move to using autoloading throughout the framework. This solves a number of performance issues, as well as simplifies coding dependencies (particularly exceptions).</li>
<li><strong>Namespaces</strong>. PHP namespaces benefit frameworks and libraries more than any other code bases, and ZF can benefit from it greatly, particularly with components such as Zend_Search_Lucene and Zend_Controller. However, adopting namespaces does not come without a cost: all code will need to be rewritten to define and use namespaces. This will be the single biggest BC break we introduce.<br />
We also plan to introduce a separate namespace for unit testing, and are currently looking at either \test\zend, \zend\test, or \zendtest. This, along with per-component namespaces, will help prevent naming collisions within the test suite.</li>
<li><strong>goto</strong>. Goto is often considered "evil," but is invaluable when creating Finite State Machines (FSM) and parsers; usage of goto will be evaluated on a case-by-case basis. Some examples of components that could potentially benefit from such an implementation include Zend_Search_Lucene (which already implements a FSM), the MVC (more below), Zend_Ical, and Zend_Markup (though not all of these may make use of it).</li>
</ul>

<ul>
<li><ac:link><ri:page ri:content-title="Plugin Architectures" /><ac:link-body>Specifics on Plugin architecture changes</ac:link-body></ac:link></li>
</ul>

<h2>MVC Implementation</h2>

<p>Our current MVC implementation is increasingly adding overhead to the dispatch cycle, slowing down the request cycle. While you can squeeze additional performance out of it via stripping require_once calls and using autoloading, the fastest requests are still far short of other, slimmer frameworks (CodeIgniter and the various new microframeworks come to mind here).</p>

<p>We are considering several potential approaches to rectify this situation. As mentioned in the previous section, we will be refactoring a number of components to provide strict interfaces. This, along with good documentation of these interfaces, will allow for easier extension and customization of ZF components. This frees us to provide a more conventions-based approach with ZF's MVC layer. The benefit to this is that it makes it possible to streamline the MVC code to just what's necessary for the 80/20 case it was designed for – while still providing flex points (via the interfaces) for customization.</p>

<p>Second, one approach other frameworks (both PHP and otherwise) are using is to provide explicit mapping of URL routes to controllers (a prime example is Horde_Routes, which is in turn based on the Python Routes project, which was in turn inspired by Ruby on Rails). This approach is potentially slightly less RAD friendly (after developing your controllers, you then need to add them to the map), but has the benefit of simplifying the dispatcher (the controller and action are known and do not need to be discovered) while still offering lazy loading. We will be looking into this to either offer as an alternate implementation or as part of the core offering.</p>

<p>Finally, one possibility offered by PHP 5.3 is the idea of having the front controller be a state machine, due to the addition of <em>goto</em> to the language. This would make it possible to define specific application states and easily jump to them, solving several issues that currently occur due to operating within a loop. It's also a common paradigm particularly with event-driven architectures, and should be somewhat familiar to JS and/or GTK developers.</p>

<p>For more information on proposed MVC refactoring, please visit the following pages:</p>
<ul>
<li><a href="http://framework.zend.com/wiki/display/ZFDEV2/Zend_Controller+2.0">Zend_Controller 2.0</a></li>
<li><a href="http://framework.zend.com/wiki/display/ZFDEV2/Zend_Controller_router+2.0">Zend_Controller_Router 2.0</a></li>
<li><a href="http://framework.zend.com/wiki/display/ZFDEV2/Zend_View+2.0">Zend_View 2.0</a></li>
<li><a href="http://framework.zend.com/wiki/display/ZFDEV2/Zend_Session+2.0">Zend_Session 2.0</a></li>
<li><ac:link><ri:page ri:content-title="Zend_Form 2.0" /></ac:link></li>
</ul>

<h2>Other components</h2>

<ul>
<li><a href="http://framework.zend.com/wiki/pages/viewpage.action?pageId=8946888">Zend_Soap 2.0</a></li>
<li><a href="http://framework.zend.com/wiki/display/ZFDEV2/Mail+sending+and+building+enhancements+2.0">Zend_Mail 2.0</a></li>
</ul>

Labels:
user user Delete
authentication authentication Delete
module module Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Nov 11, 2009

    <blockquote><p>there will be no renaming of components just for naming consistency</p></blockquote>

    <p>Why not? All code (both within ZF as well as apps depending on it) will have to be reviewed anyhow since class names will be changed to allow for namespaces.</p>

    1. Nov 11, 2009

      <p>Renaming the components will make migrations harder for developers. If most migration can be done simply by substituting '_' with '\', it's a much easier story.</p>

      1. Nov 11, 2009

        <p>Ok, but why not get rid of any naming inconsistency now with 2.0. It is not such a big deal to do the renaming from Zend_Foo_Bar_Whatever to Zend\Bar\Foo\Whatever. Every IDE nowadays can do this without much effort. These changes only need to be documented in a migration guide.</p>

        <p>jm2c</p>

        <p><em>update: added an "in" before consistency</em></p>

        1. Nov 12, 2009

          <p>+1 Well, this is the time to do it. We don't know when we will get another such opportunity. Moreover, it is a good way to educate people who will use Zend Framework about naming conventions.</p>

        2. Nov 12, 2009

          <p>+1 for fixing all naming issues now. Also:</p>

          <blockquote><p>Our goal with ZF 2.0 is to improve the overall consistency of the project. With consistent APIs relating to constructors, options, and exceptions, developers can more readily grasp the basics of each component and move on to specifics of usage.</p></blockquote>

          <p>If you accept that naming is a critical part of the design of the code, then it would seem to be in our best interest to seize this opportunity to fix as much as possible in pursuit of this goal. The longer bad names stay around, the higher their cost to fix will become. IIRC, I believe that Kent Beck said in the Refactoring book that you should make a point to fix bad names before other issues. Good names may be the single biggest factor affecting the understandability of the code.</p>

      2. Nov 11, 2009

        <p>+1 for removing any naming inconsistency. I do not think the migration path will be much harder, and the added consistency would be worth it in the long run.</p>

        <p>( Ralf I assume you wanted an "in" before that "consistency" in the previous comment. funny... )</p>

        1. Nov 11, 2009

          <p>Yes Jacob you are right. It must have been too late last night after a hard days work. Sorry for the confusion.</p>

    2. Nov 12, 2009

      <ac:macro ac:name="note"><ac:parameter ac:name="title">Allowing Class/Component renaming</ac:parameter><ac:rich-text-body>
      <p>Based on the comments and other discussions, I've stricken the sentence indicating we will not rename components for naming consistency. This can be addressed with migration scripts, and we will make this an additional task for the 2.0 roadmap.</p></ac:rich-text-body></ac:macro>

      1. Nov 12, 2009

        <p>The meaning is... change to names allowed? Two migrations of class names are too much imho, and addressing consistency now is a better choice than having to deal with it later.<br />
        Why underscore_lowercase_keys? Is it not simpler to use camelCaseKeys since the translation to setters involve only a ucfirst()/lcfirst()?</p>

        1. Nov 12, 2009

          <p>We'll review changes on a case-by-case basis (instead of having a blanket ban).</p>

          <p>As for underscore_lowercase_keys, the issues are thus:</p>
          <ul>
          <li>Case sensitivity issues with options are very hard to track down</li>
          <li>Case sensitivity issues have led to a variety of maintenance problems in existing components, including issues determining how to resolve plugin names to class names (FrontController vs. Frontcontroller, etc.)</li>
          <li>It's relatively simple to transform underscore_lowercase_keys to underscoreLowercaseKeys using PHP's string functions, which in turn makes it:
          <ul>
          <li>undetrivial to cache object method names and do case sensitive comparisons later</li>
          </ul>
          </li>
          <li>They're more readable in configuration files</li>
          </ul>

          <p>Overall, the use cases become simpler and easier to support in a uniform manner. If applied throughout the framework, this becomes a simple rule for developers to learn.</p>

          1. Nov 13, 2009

            <p>Imho case sensitivity it's the way computer works. but it is a personal opinion. What am I worried about is the consistency of the keys with camelCase method and class names (someone confused about when he has to use lowercase_underscore and camelCase).</p>

            1. Nov 13, 2009

              <p>It'd be really, really simple: option keys and configuration keys are always underscore_separated. Properties and methods are always camelCased. 1:1 matching between them.</p>

              <p>Case sensitivity may be how a computer works, but it's a bitch to debug; I can't tell you how many times I've seen posts on the mailing lists or issue tracker where the problem ended up being option case – nor how many back and forth messages/comments it takes to determine this. It's relatively easy to determine when the key in question refers to a class name, but other options are less obvious.</p>

  2. Nov 11, 2009

    <p>How about focusing on the extendability of classes? I can't tell you how many times I've run into a situation where I need to modify the behavior of a method, and I've run into either private variables (without getters/setters) or final classes in the ZF. There are definitely cases for their use, but I feel that there are a lot of private variables that could be protected. Also some classes are declared final, but shouldn't be. I can't remember any specific examples off hand, but I think the REST server/client has a couple.</p>

    1. Nov 12, 2009

      <p>Simply making classes non-final or turning private to protected does not make something extensible. Without any further thought this makes them only "hackable". There is a very good rule of thumb for inheritance: Design and document for inheritance or else prohibit it. Designing a class for inheritance means that the extension points are well-defined, the consequences of extending a class are documented, etc. That makes the class "robust".<br />
      By just making classes non-final and members protected instead of private you indirectly increased your maintenance burden and the chance for breaking backwards compatibility. Every single protected member might now be used by some application that relies on it, even renaming breaks BC. Every single protected method might now be overriden or used in a subclass, causing strange side-effects that were never anticipated.</p>

      <p>The worst example I read somewhere, I think it was on a cakephp wiki page, is that "all members should be protected, this is a framework and thus should be extensible". This is just not extensibility or at least a very unstable and unreliable extensibility.</p>

      <p>Maybe you're frustrated because you were run into such situations where you needed to modify the behavior of a class in a way that was not intended. Probably you would've been happier at that point when it would've been possible to just extend that class or override that particular method. But you would be frustrated later when your code broke all of a sudden because the code you relied upon was refactored. If you demand everything to be protected/non-final you put a huge burden on the framework developers to maintain backwards compatibility.</p>

      <p>Its no secret that inheritance breaks encapsulation to a certain degree anyway.</p>

      1. Nov 12, 2009

        <p>You make some excellent points Roman, I agree that in general one should use stricter OO concepts (final and private) to enforce particular use cases in ones own code. But that is a tougher dance to dance when you are a general purpose framework.</p>

        <p>Generally, framework component developers cannot identify all use cases when authoring a new component. Like all great technologies, the really interesting use cases don't really become apparent until after people have had a chance to play with the code. That said, when we decide to restrict usage of final and private, and static state for that matter, it's because we feel there is both a public API as well as an extension point API that should be available to consumers. This allows us to not lock in (via BC) to a particularly inflexible and restrictive API, and also allows consumers to extend in ways that otherwise would have presented pain points. This also allows us to grow the original use case, and further unit test them as new use cases and possible extensions become available.</p>

        <p>Most major changes that go into ZF components get reviewed for both of these potential BC breaks: on the public known API as well as the protected extension API. And we do our best to ensure as much BC as possible on the extension API.</p>

        <p>Then there are also some advantages when unit testing, but that's a whole other topic <ac:emoticon ac:name="wink" /></p>

    2. Nov 12, 2009

      <p>I'm not sure where you're looking, but there are exactly four classes marked final withing ZF – 2 in the InfoCard component, one in AMF, and Zend_Version. I hardly think this will be an issue – but we will review those cases. (In your specific example of the REST server, it will be going away in 2.0, and we recommend using the new Zend_Rest_Route to build your RESTful applications via the MVC.)</p>

      <p>Regarding private variable usage, we actually recommend protected visibility except in those cases where overriding could cause the implementation to break. There may be a few places we need to review the visibility, but I do not expect too many changes in this regard. As Roman notes, visibility is not the key to extensibility; class and component design is. The flex points should be well-defined and documented.</p>

      1. Nov 12, 2009

        <p>I was wrong earlier about making classes final, I forgot my use case... It was actually making methods final. </p>

        <p>So here is a situation I ran in to... There is a REST API I wanted to consume, I knew the results of the REST calls I was making wouldn't change very often (maybe once a day), so I naturally wanted to cache the results. The static method getHttpClient in Zend_Service_Abstract is final, there is no way to use a custom HttpClient... Also, the HttpClient as it exists right now, doesn't support caching (and for good reason, this use case is very obscure). However, I couldn't find a good solution to implementing caching in my scenario, without wrapping the entire process in a caching statement... (I'd rather cache the calls, not the final Zend_Rest response).</p>

        <p>I am by no means arguing for globally removing private or final without consideration... just to review the places it has been used in the past and consider whether or not it is necessary. </p>

        <p>Maybe (possibly silly again), but having a place where all major Zend components where caching makes sense... Again this is just one tiny problem, but a great chance to review old code.</p>

      2. Nov 13, 2009

        <p>I'm still looking over the Controller 2.0 and Controller_Router 2.0 docs, but I didn't see any mention of Zend_Rest_Route in the classes section of the Router 2.0 wiki page? It will need to be updated along with the other routes, right?</p>

        1. Nov 18, 2009

          <p>That's correct. The Zend\Rest\Route will have to be updated according to the new interface.</p>

  3. Nov 12, 2009

    <p>This all looks great, I like the idea of design by contract, lack of clear api's in some of the classes have been frustrating at times.</p>

    <p>Your FSM MVC example is also very interesting I look forward to watching this grow <ac:emoticon ac:name="smile" /></p>

  4. Nov 12, 2009

    <p>I've read through all the docs on the wiki, and followed the discussion in the mailing list. First of all, let me say that this looks really good. I like the direction ZF is headed, and it certainly seems that we have enough enthusiastic contributors behind the wheel to make the framework go in a direction we're all happy with in the end. This needed to be said, because my notes below might come across as more harsh than they actually are.</p>

    <p>Unified constructors. This is simply a bad idea. be assumed that all classes are "configurable" objects (I mean who are we, jQuery?). Granted, some of the classes in the framework (I've even written such a component myself :S) benefit from taking $options as a single constructor param, but most don't. Sure, an array is an efficient data structure in PHP, but we lose <em>all the good stuff</em>, namely a self-documenting syntax which is easy to learn, because it is typed and can be automatically parsed by IDEs. Not only IDEs, actually. My favorite way of learning a class is by looking at the constructor, either by opening the file directly, or looking at auto-completion suggestions in the IDE. I expect to find a clear overview of the required params for constructing the class in a valid state. This won't be the case with an $options array, which has to be manually written in a docblock. Sure, IDEs <em>could</em> parse this information, but we all know that won't be a viable feature for several years, and only in a few selected IDEs (probably as an extended "ZF" feature for Zend Studio which won't be contributed back to the original PDT project, and then we have it going with slow bureaucracy at least until PHP 6.0 is released and the whole PDT project will have to be rewritten once again).</p>

    <p>But it goes beyond syntax and "pedagogical" reasons. I'd take it as far as to say that if this is a feature we <em>need</em> because constructor params change too frequently, something is completely funked further down the line. A constructor shouldn't need to take a whole load of params to construct the object in a valid state, it should be simple. Perhaps the class has too much responsibility, and should be refactored separate its behaviour into more logical groupings. Of course this can't always be done, but I'd still argue that in most cases a constructor shouldn't take more than 3 params. This may sound blatantly provocative, so take it with a pinch of salt, but think about it; wouldn't it be nice? Supear-easy to get an overview and learn the API.</p>

    <p>For classes that absolutely <em>have</em> to take a single $options param, there is still a way to do it which is more easily parsed by both humans and IDEs. Make an FooOptions class which is consumed by the Foo constructor. This is something that is done in several other languages, and from my experience it works well when the constructor needs a bunch of options. Example, let's say we have an an <code>Application</code> class that takes 10 param. Instead of putting those params in a naive array, make an <code>ApplicationOptions</code> class with 10 properties (and/or getters/setters), which allows us to do <code>public function _<em>construct(ApplicationOptions $options)</em></code><em>. This allows for auto-completion in IDEs, it's easy to understand, OOP-wise it's easy to extend, and way easier to maintain in the long run than an array. And of course, all such classes (and indeed all constructors) should follow the principle of _convention over configuration</em>, i.e., the user should have to specify as few options as necessary. A nice side effect for this pattern is that those options class may contain extra logic if that's something you need.</p>

    <p>I don't buy the argument that this makes (type 3) dependency injection a breeze. Surely, implementation-wise it's a breeze, because you can stuff whatever you like in an array and hope for the best, but dependency injection shouldn't trade off readable code, and you shouldn't have to depend on dependency injection to be able to create a class.</p>

    <p>So yeah, I'm somewhat against unified constructors. Moving on...</p>

    <p>Exceptions. What's the deal with those marker interfaces and having to wrap stuff to use it? From what I can tell, the argument narrows down to this: it allows us to catch "zend" exceptions, or "zend\somecomponent" exceptions. Let's say I'm writing some code in the zend\navigation namespace, and want to throw an InvalidArgumentExcception. Do I have to a) make an empty Exception marker interface in the namespace, then b) make an InvalidArgumentException that extends SPL's InvalidArgumentException and implements the marker interface? I'm asking not because I'm trying to bash the sketched solution, but because I find it unclear. It seems <em>extremely</em> cluttered, I have to admit, and there is no apparent use-case where you'd benefit from catching exceptions based on component. Furthermore, an InvalidArgumentException is an InvalidArgumentException – its logical meaning doesn't change whether it's used in the zend\navigation namespace or the zend\view namespace. I've never understood why ZF does things so differently with exceptions than other languages/frameworks I know. Nowadays we're just throwing the general "component exception" no matter what, we don't have exception classes that carry any meaning by themselves. This is a shame, because it really is much easier to work with exception classes you immediately understand what means. And to cap it all off, this would mean you wouldn't have to catch "general" exceptions where it doesn't make sense.</p>

    <p>Let's use SPL exceptions directly, that's what they're there for. No need to wrap any exception class or make marker interfaces, because it doesn't really solve anything. I know there has been talk about making "translatable" exceptions and whatnot, but it doens't look like this is happening any time soon, and in case it does, it could be implemented by retrofitting a TranslatableException interface or by introspecting general exception classes (which would make it work outside the ZF world as well).</p>

    <p>Now for the finale, our favorite topic of discussion: class/interface naming. I wrote a comment about this in the Controller 2.0 page yesterday, but it seems it got clogged in the tubes or something. I know this has been discussed before, but I'm curious to see the reasoning behind the current <code>Interface</code> suffix scheme, because as I recall it, this has never been anyone's favorite. First off, Interface is a long word, and takes up quite a bit of horizontal space. I'm not trying to be a 80-characers-per-line nazi here, but I generally am in favor of shorter, more descriptive names. Secondly, the <code>Interface</code> prefix looks weird in variable declarations and params, because we're passing discrete implementations, not interface. We all know this, of couse, but I can't help but to find it irrational/illogical. "I'm passing this event interface to the _<em>invoke() method". We don't say that, we say "I'm passing this _event</em> to the __invoke()" method. I guess what it comes down it is that the <code>Interface</code> prefix simply doesn't read well.</p>

    <p>Regarding abstract classes, what's the currently preferred scheme? Is an <code>Abstract</code> prefix/suffix considered good practice? I'm actually okay with an <code>Abstract</code> prefix where it's absolutely necessary, but generally it's always possible to give it a more descriptive name. <code>Base</code> may also be considered as a prefix/suffix, because this reads well and actually indicates what the class is – a base for other classes to extend. Another option, which I feel haven't been given enough consideration, is to use a <code>Default</code> prefix. This is particularly handy in situations where you have an interface and a default implmentation of the interface, like with the currently suggested Controller 2.0 implementation. Also, I've seen this used in several other languages (and yes, that <em>is</em> an argument, because we all feel comfortable with what we already know).</p>

    <p>Instead of ...</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    class ActionController implements ActionControllerInterface
    {
    public function __invoke(EventInteface $event) { }
    }
    ]]></ac:plain-text-body></ac:macro>

    <p>... let's use:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    class DefaultActionController implements ActionController
    {
    public function __invoke(Event $event) {}
    }
    ]]></ac:plain-text-body></ac:macro>

    <p>There, fixed it. A lot easier to read, and frankly it just looks way cooler. On a semi-uninteresting sidenote; shouldn't the controller take a more specific Event type, such as MvcEvent, ControllerEvent, or DispatchEvent? Let's not forget the mantra "descriptive names". I doubt it's the intention that a controller should be able to dispatch <em>any</em> event. Also, with descriptive names (as opposed to several components having just <code>Event</code> classes like with <code>Exception</code>), we wouldn't have to alias imports if we were to use events from several namespaces in the same class.</p>

    <p>Urr, I think that's it for now. It's a bit tl;dr, but I hope I could get some points/opinions through.</p>

    <p>And again, this is not bashing out on the framework just for the hell of it, because I really do like the direction of the framework, and I'm not trying to rain on anyone's parade.</p>

    <p>I think the essense of what I'm saying is that code should be self-documenting and easy to read, easy to learn.</p>

    1. Nov 13, 2009

      <p><strong>Interface naming:</strong><br />
      I'm not a fan of long names but I think it is important to see if it is an interface and abstract class or a normal class. This makes is more easy to debug and understand the code.<br />
      In my opinion a good naming would be to add the prefix "I" to interfaces and the prefix "A" to abstract classes.<br />
      EventInteface -> IEvent<br />
      EventAbstract -> AEvent</p>

      <p><strong>Exception interface:</strong><br />
      The use of this marker interface is very flexible and don't make it more complicated. Now you can determine if you would like to catch an exception by SPL name or to catch exceptions from a specific component (or from all zf components)</p>

      <p>My only objection is the naming of the interface \Zend\FooBar\Exception. It isn't based on interface naming standard and block the name for a simple component exception that extends directly the exception class.<br />
      Please rename the exception interface to \Zend\FooBar\IException or \Zend\FooBar\ExceptionInterface</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      interface \Zend\IException
      {}

      interface \Zend\FooBar\IException extends \Zend\IException
      {}

      class \Zend\FooBar\Exception extends \Exception implements \Zend\FooBar\IException
      {}
      ]]></ac:plain-text-body></ac:macro>

      1. Nov 13, 2009

        <p>We have already defined how interface and abstract naming will work in the coding standards, and this will not change in 2.0 (the definitions were actually intended <strong>for</strong> 2.0, to be honest). They are:</p>
        <ul>
        <li>Interfaces are suffixed with "Interface": ActionControllerInterface</li>
        <li>Abstract classes are suffixed with "Abstract": ActionControllerAbstract<br />
        This policy keeps them grouped together and with their default implementations. Additionally, it's an easy rule to remember and implement for non-native English speakers.</li>
        </ul>

        <p>As for Exceptions not following this rule, that is because there may be components where there is no Exception marker interface, and others where there is; it's more consistent to use the same name regardless of implementation.</p>

        1. Nov 13, 2009

          <p>Your comment wasn't posted when I posted my comment below, so I didn't see it.</p>

          <p>So this is nailed in stone now? I guess it's okay to be consistent with such a naming scheme, even though I want to pull out my hair every time i suffix something with Interface <ac:emoticon ac:name="wink" /></p>

        2. Nov 13, 2009

          <p><strong>Interfaces are suffixed with "Interface": ActionControllerInterface</strong><br />
          Sounds ok for my. Essentially it is viewable by name. <ac:emoticon ac:name="smile" /></p>

          <p><strong>Exception interface:</strong><br />
          > As for Exceptions not following this rule, that is because there may be components where there is no Exception marker interface, and others where there is; it's more consistent to use the same name regardless of implementation.</p>

          <p>I don't understand this. The definition is (on top):<br />
          "Exceptions. Each component will have an Exception marker interface, with exceptions defined for discrete exception types thrown by the component."<br />
          -> This means for me in ZF2.0 <strong>ALL</strong> components have to implement this marker interface.</p>

          <p>And the next sentence:<br />
          "The concrete exceptions will either extend the global Exception class or an SPL Exception, and also implement the component Exception interface."<br />
          -> How can the component implement an Exception which extends the <strong>global Exception</strong> class if the name of the marker interface is \Zend\FooBar\Exception ?</p>

          <p>Generally why we say <strong>Allowing Class/Component renaming</strong> for naming consistency but add a new inconsistence ?</p>

      2. Nov 13, 2009

        <p>What's the benefit of catching exceptions per component? Initially it sounds like a useful feature, but I've never had the need to do so.</p>

        <p>Regarding interface naming, I also like the simple "I" prefix – ISomething – but we shouldn't need to specify in the interface name that it is an interface. It's derived from the context where it's used.</p>

        <p>I don't care for the "A" prefix for abstract classes. It looks weird, and I don't see why ZF should define its own naming scheme when we've had others for <em>years</em> in other languages and libs.</p>

        1. Nov 13, 2009

          <p>The benefit comes when you want to differentiate your own exceptions from those of the framework or those from other 3rd party libraries. Just because <em>you're</em> not doing it doesn't mean others are not.</p>

          <p>As for the I/A stuff, see my other reply to you.</p>

    2. Nov 13, 2009

      <p>Robin, thank you for your detailed and well-considered comments.</p>

      <h4>unified constructor</h4>
      <p>The original thought behind the unified constructor is that, because this has become a common pattern throughout the framework, we should make it explicit. That said, you, Stefan Priebsh, and others are providing some excellent arguments against the concept – and I particularly appreciate that you are providing some alternatives to the practice.</p>

      <p>The areas where the pattern has become useful can be lumped into two primary categories:</p>
      <ul>
      <li>Plugin/adapter classes</li>
      <li>Service classes<br />
      The first case encompasses components such as Zend_Form (particularly elements, validators, filters, and decorators) and Zend_Application (particularly resources); the second refers to the various Zend_Service consumables, a number of which have, due to changes in the remote APIs, needed to change constructor signatures. In the case of plugin/adapter classes, typically the objects are being created via a factory, and methods are not being called until after instantiation. In the case of service classes, often the values passed to the constructor are necessary in order to connect to a given web API – but will not be used until a call to the API is made.</li>
      </ul>

      <p>In both cases, the information is typically not <em>required</em> by the constructor. As such, having a "Configurable" interface that defines <code>setOptions($options)</code> would likely suffice. This interface should be fairly uniform, particularly in implementation, to ensure that developers can use it easily.</p>

      <p>I also like your idea of using configuration "containers" to pass to either the constructor or setOptions(). This has benefits particularly for those using IDEs, and provides an OOP paradigm; that said, I think allowing an array and/or Zend_Config object also should be allowed. I'd like to examine this idea more.</p>

      <p>For now, let's operate under the assumption that the "unified constructor" is not set in stone, and may be replaced with one or more other recommendations that will serve to solve some of the same issues regarding APIs.</p>

      <h4>exceptions</h4>
      <p>First off: this use case actually did not originate with myself or the Zend team, but was one brought up and agreed upon during the original PHP project interoperability group meeting at php|tek in 2009. If we <strong>don't</strong> do this, we'll be operating differently than other frameworks – which makes that particular point of yours moot.</p>

      <p>The rationale is clearly described in the narrative, but I'll bring up the salient points:</p>
      <ul>
      <li>It allows catching the exception as an SPL/native Exception</li>
      <li>It allows catching the exception as a specific vendor/component/subcomponent exception</li>
      <li>It encourages creation of well-defined and descriptively named exceptions</li>
      </ul>

      <h4>interface/abstract naming</h4>
      <p>I thoroughly agree with your points on naming. There, it's said.</p>

      <p>However, there are other points of view to consider. Yes, <em>you</em> have a good grasp of the English language – but not all non-native speakers do. Coming up with a good name for an interface or abstract class can be difficult, particularly in a language as nuanced as English (e.g.: what do you call a Person interface? Personable? not quite the connotation desired...). Additionally, if you have both an interface and an abstract implementation sitting beside a concrete implementation, naming becomes even more difficult. Consider the case of routing: a good name for an interface might be "Router", but what do you call the concrete implementation? or an abstract implementation?</p>

      <p>Finally, while API docs and IDEs may make finding the interfaces and abstract classes easy, what if you don't have the API docs in front of you, or don't use an IDE? How do you distinguish, by glancing through the filesystem, which class is an interface, which an abstract, etc?</p>

      <p>Having simple, clear naming rules alleviates these issues:</p>
      <ul>
      <li>Abstract classes end in the word "Abstract": PersonAbstract</li>
      <li>Interfaces end in the word "Interface": PersonInterface</li>
      </ul>

      <p>Sure, these may be somewhat ugly, but having easy to follow rules solves all of the above issues. It also fits your criteria of the code being self documenting, not only in how these elements are defined, but in how they are named.</p>

      1. Nov 13, 2009

        <p>Thanks for taking the time to reply and explain some of the thoughts behind the decision. It's cool to see that something as nerdy as "unified constructors" can upset and engage so many people <ac:emoticon ac:name="smile" /> People really care about the framework, which is a good thing.</p>

        <p>Also, thanks for summarizing the PHP Interop Group thingy. I was given a link on the mailing list, but couldn't really find anything on the topic at the URL. To be honest, I still don't get it, but that's fine. As long as I get to throw SPL exceptions, I'm happy.</p>

        <p>I won't continue to nag about exceptions and class naming, because let's face it: it doesn't really matter that much. It's not the end of the world whether we go for one naming scheme or the other, the functionality remains the same.</p>

        <p>I'd still like to answer some of the (rhetorical) questions you raised, though. (This time just for the hell of it. It's Friday night and I need a break from glaring at AS3 code. FML)</p>

        <blockquote>
        <p>Q: What do you call a Person interface?</p></blockquote>

        <p>A: Person.</p>

        <blockquote>
        <p>Q: Consider the case of routing: a good name for an interface might be "Router", but what do you call the concrete implementation? or an abstract implementation?</p></blockquote>

        <p>A: <code>interface Router</code>, <code>class DefaultRouter</code>, <code>abstract class AbstractRouter</code> (or <code>abstract class RouterBase</code>)</p>

        <blockquote>
        <p>Q: ... what if you don't have the API docs in front of you, or don't use an IDE?</p></blockquote>

        <p>A: I wouldn't expect anyone to learn the ins and out of the framework architecture without ever using some sort of documentation. I'm thinking that if you're really looking for abstract classes or interfaces in a specific namespace, you probably already know what you're looking for (to some extent).</p>

        <blockquote>
        <p>Q: How do you distinguish, by glancing through the filesystem, which class is an interface, which an abstract, etc?</p></blockquote>

        <p>A1: Again, you probably have an idea what you're looking for.<br />
        A2: There aren't <em>that</em> many interfaces or abstract classes in any given namespace. Actually, in most cases (yup, I skimmed through the working dir with <code>find</code> and <code>grep</code>) there's just one interface and one abstract class. Determining which is which just by looking at filenames is not at all an impossible task, even if you suck at English.<br />
        A3: This argument falls through when introducing Phar packaging.</p>

        <blockquote>
        <p>It also fits your criteria of the code being self documenting, not only in how these elements are defined, but in how they are named.</p></blockquote>

        <p>Quoted for truth.</p>

        1. Nov 13, 2009

          <p>Thanks for the response, Robin. Had me laughing for the first time today!</p>

          <p>I just want to point out one thing with the naming questions: you came up with some right off the bat, but even in those, there's a ton of variability – does the indicator of abstract (regardless of what it is) come before or after the class/component name? Does "default" or "base" indicate abstractness? etc. The goal of the naming conventions is to take some of the variability out and make it consistent, particularly between different <em>developers</em>. </p>

          <p>As you say: in the end, it doesn't really matter that much – so long as we're all following the same rules.</p>

          <p>(I'll dig up the link to the Interop group statement on exceptions soon and post it.)</p>

          1. Nov 13, 2009

            <p>Just to clarify.<br />
            1. Yes, "Abstract" would always be a prefix, so it reads as "an abstract DoesSomethingClass".<br />
            2. "Default" indicates a concrete implementation – "the default DoesSomethingClass".<br />
            3. Not too fond of "base", really. Let's forget I even said that.</p>

    3. Mar 10, 2010

      <p>I don't know how late-to-the-game I am with my reply, but I felt compelled to point something out to Robin, and other anti-unified constructionists out there: You can still "document" the constructor even with just an array as a parameter. Take the following code snippet as an example:</p>

      <ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
      <?php
      class Foo {
      public function __construct($options = array('foo' => '', 'bar' => '', 'baz' => ''))

      Unknown macro: { var_dump($options); }

      }

      $foo = new Foo;
      ?>
      ]]></ac:plain-text-body></ac:macro>

      <p>If a unified constructor were to define the "default" options that it accepts in the constructor, then in my opinion, we could have the best of both worlds. </p>

      <p>PS. I have not yet finished reading all of the comments, so if this has already been said, then please accept my apologies. I just wanted to get this out there before I forgot what I wanted to say. <ac:emoticon ac:name="smile" /></p>

  5. Nov 13, 2009

    <p>I strongly suggest not to introduce the unified constructors.</p>

    <p>The main reason is that you give away the two main advantages of dependency injection through the constructor, explicitness and the ability to use type hints. You'd force developers to look at the source code to find out about required or optional dependencies (I'm just focussing on the dependency injection aspect of the parameter arrays here). Type hinting is possible in the individual setter methods, but not in the general setOptions() method. This will lead to problems, or require people to explicitly code type checks.</p>

    <p>Another reason, albeit less important, is that you make it a lot harder to figure out which constructor arguments are optional. Constructor arguments with default values make that very easy.</p>

    <p>The Foo implementation shown above has a hard-coded, implicit dependency on Option, which is really, really bad. Number one, you have to look at the Foo source code to learn about the dependency, as Option does not show up in the Foo API. Number two, you cannot easily swap out Option for anything else. Late static binding can obviously help, but if somebody wants to extend Option, they will still have an unnecessary hard job.</p>

    <p>In the above example, Option is basically a registry through the backdoor. Pass $options with "everything" to the Foo constructor, let Option pick the values that Foo need by checking for which setters there are. I see a high potential for abuse.</p>

    <p>In addition, Option makes some assumptions, for example the presence of a public setter method named setSomething(). Underscore-separated names are converted, which implies that you run into all the troubles of named parameters when renaming a setter method: the IDE is not going to help people, they have to figure out that they must fix their named parameters throughout the code. If you choose that route, you have to throw an exception in Option when a setter does not exist - otherwise people have to debug their code just to find out that due to a typo, one option value has not been set.</p>

    <p>Last but not least, the above example <em>requires</em> a public setter for everything that I may want to pass in as a constructor argument. Especially when it comes to injecting dependencies, this is in most cases not what I want: I want to <em>force</em> users of my class to pass a dependency as a constructor argument, but I want to <em>prevent</em> them from being able to change that dependency later. By requiring a public setter for everything, you introdoce a lot of potential for people to screw up.</p>

    <p>To sum it up, in my opinion the disadvantages of unified constructors by far outweigh the advantages they offer.</p>

    1. Nov 13, 2009

      <p>I would also prefer to reduce the dependencies instead of having all these objects passed in the constructor, but it is not simple. I guess the Option class is only a tentative to avoid repetitive code, and it cannot be injected, because it is used to inject.</p>

      <p>For the setters problem, it would also be good to prevent further changes to the class, but this can be achieved via setters that accept a value only if it is not already defined.<br />
      Since there is a lot of dependencies in Zend Framework classes, why not get rid of the Option class and using setter injection instead? Since the actual construction would be performed automatically by a injector/provider/container there is really no difference. We can even adopt a new standard and name the setters injectCollaborator(), injectOtherCollaborator() and so on.</p>

    2. Nov 13, 2009

      <p>I agree to some degree. If Option is indeed used for this, it should follow design by contract, and therefore the parameter should imho do the configuring, not a some hard-coded class. That would get rid of your dependency injection troubles. <br class="atl-forced-newline" /></p>
      <ac:macro ac:name="noformat"><ac:plain-text-body><![CDATA[
      class Foo {
      function __construct($options = null) {
      if($options instanceof ConfigureInterface)

      Unknown macro: { $options->configure($this); }

      else

      Unknown macro: { // maybe try something else, or throw an exception, whatever. }

      }
      }
      ]]></ac:plain-text-body></ac:macro>
      <p>Zend_Config for example could implement configureinterface and configure the Foo class in the "standardized" PHP way, but you could replace it easily with your own implementation of the ConfigureInterface.</p>

      <p>Finally array options, they could (and imho should) be disregarded, and simply be wrapped in a "ConfigureInterface" that handles arrays, for example Zend_Config itself, or maybe the "unified" constructor could handle this for you, which would be a "service" to the user, more than a recommended usage:</p>
      <ac:macro ac:name="noformat"><ac:plain-text-body><![CDATA[
      class Bar {
      function __construct($options = null) {
      if(is_array($options))

      Unknown macro: { // default to standard Zend_Config implementation}

      elseif($options instanceof ConfigureInterface)

      }
      }
      ]]></ac:plain-text-body></ac:macro>
      <p>As for required dependencies, they (imho) shouldn't be in the options altogether. They should be simply part of your constructor definition:</p>

      <ac:macro ac:name="noformat"><ac:plain-text-body><![CDATA[
      class Baz extends Foo {
      function __construct(SomeDependencyInterface $dependency, $options = null)

      Unknown macro: { parent}

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

    3. Nov 13, 2009

      <p>Stefan – thanks for your comment!</p>

      <p>Based on your arguments and those others have made, I'm definitely inclining to revisit this decision, and you can see more of my thoughts on this in a reply to Robin Skoglund further up the thread. As I note there, the pattern really makes most sense for those classes being used as plugins/adapters, or for classes where we know that constructor arguments may vary over time (concrete service consumable classes – the Zend_Service tree, basically). Even so, there may be other approaches we can consider – and I'm willing to do so as long as we can approach all such cases in a uniform way. One issue ZF is often take to task for is the inconsistency of API, and that's one thing I want to address with 2.0.</p>

  6. Nov 15, 2009

    <p>Since the dispatching process and the "plugin" systems are going to change, I was wondering if it wouldn't make sense to make their design suitable for C implemented extension. Those two "components" really need to be as fast as possible and I assume that a "simple" PHP extension, which implements support for them, would really help to obtain some very good speed gains.</p>

    <p>Those features are common enough in modern web development that an extension like that could also be useful for other frameworks.</p>

    1. Nov 15, 2009

      <p>This actually sounds like a crazy cool idea. +1 from me</p>

    2. Nov 15, 2009

      <p>Offering both would be best in my opinion. Not everybody will be allowed to run custom PHP extensions on his platform. There could be some interfaces implemented in C by the extension and in PHP.</p>

    3. Nov 15, 2009

      <p>Some people apparently have thought about doing this already pre-1.0, and more recently we also gave that a shot ('round the release of 1.7). However, because we didn't have time, nor enough C programmers we froze the project for a while/indefinitely (we'll see which of the two).</p>

      <p>Having said that, I do think porting stuff to C++ is a good idea. However, since ZF is a PHP framework, design decisions should be made with (primarily) having PHP in mind, not an other language. Basically anything done in PHP can be ported to C+<span style="text-decoration: underline;">, and considering that I think we should first have something stable and working in PHP, before people start porting it to C</span><span style="text-decoration: underline;">. Also, due to the time it takes to port PHP to C</span>+ (trust me, it does..) such a PHP module would always be 'behind' with the ZF releases.</p>

      <p>One advantage; you can just run the unittests to see if all functionality was ported correctly (another pro for unittests <ac:emoticon ac:name="laugh" />)</p>

  7. Nov 19, 2009

    <p>Even though I believe that all those improvements discussed here are really good, I think - as of today - ZF is mostly lacking of good support on the Model and does have great room for improvement there, I think. I feel that part as being under-represented in the discussions so far.</p>

    <p>I would love to see the Service Layer being more exposed and more "default" so that developers stop putting business logic in their controllers and - even better - also stop putting it into the business objects. Business logic perfectly fits into the service layer and ZF could support that by making a service layer "something really normal that is there by default". ORM is another topic that - I beliebe - is already covered by ideas of integrating Doctring (2) or at least making usage of Doctrine, Propel etc. easier in ZF. Zend_Db is pretty fine, but Doctrine & Co. really provides persistence in another dimension.</p>

    <p>One thing missing also is solid support for transactions. Having something like JTA would really push ZF / PHP heavily towards "enterprise readiness". Also applications are going to be more and more distributed and therefore transaction management is getting even more important. Without solid transaction management, mission critical enterprise applications are hardly imaginable, to be honest.</p>

    <p>Thanks for taking time reading through my thoughts. Really appreciate!</p>

    <p>Michael</p>

  8. Nov 22, 2009

    <p>How about implementing request parameter mapping to action method parameters out of the box? I've seen many implementations of it, but having the option to utilize it out of the box would be nice..</p>

    <p><a class="external-link" href="http://devzone.zend.com/article/10861-Request-parameter-mapping-to-action-method-parameters">http://devzone.zend.com/article/10861-Request-parameter-mapping-to-action-method-parameters</a>
    <a class="external-link" href="http://fbdevzone.com/2009/10/request-parameter-mapping/">http://fbdevzone.com/2009/10/request-parameter-mapping/</a></p>

    1. Nov 23, 2009

      <p>Personally, I'm not terribly interested in this. The request object is mutable, and by implementing request parameter => action method parameter mapping, you actually limit the functionality quite a bit, as well as put more of an onus on the end-user developer to define the required parameters. As an example, if, in the future, they require more parameters, they will have to change the method signature.</p>

      <p>That said, with the proposed implementation, you could quite easily do this within the __invoke() method, and we could have a variant action controller type that allows it. I just do not feel it should be the default use case.</p>

  9. Dec 08, 2009

    <p>From my perspective improving performance of the MVC layer seems like the most important task. The current implementation has its "slowness" distributed over many components thereby making it very hard improve the situation. </p>

    <p>I therefore welcome a rewrite of the MVC layer very much. I would argue for making the most common use case faster even at the cost of more complexity in other use cases.</p>

    <p>Also it could be considered adding a section to the performance section of the Reference Guide that shows an example of how to make some requests go around the front controller but still use ZF components. E.g. a php file in the public directory that includes the bootstrap but does not start the MVC layer. </p>

  10. Dec 12, 2009

    <p>I have two major issues with the above proposed implementation of zend\Options. Actually three. The third being that IMO you should get rid of the classes in nodes, ALL of them. Options should have it's own package, options. So, zend\options\Options. Pretty pretty please.</p>

    <p>The first problem I have with the actual code is that passing of arrays instead of objects: it leaves no room for extension. Poor design choice.</p>

    <p>The second problem is directly related: use of a static interface. Do you really want to introduce even more static interfaces in ZF? Please no!</p>

    1. Dec 13, 2009

      <p>Please see the above discussion; we've already decided not to implement the Options class/package.</p>

  11. Dec 16, 2009

    <p>I think ZF 2.0 with a minimum requirement of PHP 5.3 is a very large mistake. Take a look at all the web hosts around. Many of the web hosts (especially shared hosts) do not yet offer 5.3. DreamHost for example says they can not move up to it until all the 3rd party PHP modules they use are supported under 5.3, they have tested it and then had a server upgrade.</p>

    <p>I can not name a single shared web host that supports PHP 5.3.<br />
    Do you expect ZF 2.0 to be used by anyone on shared web hosts?</p>

    1. Dec 16, 2009

      <p>I don't think 5.3 will be a major issue. The next version of Symphony and Doctrine will be 5.3 only, and they're both due out (probably) sometime late next year. Besides, the web-hosts will be slow to upgrade if there's no demand for it.</p>

    2. Dec 17, 2009

      <p>ZF 2.0 is not going to happen overnight; we're anticipating being ready for release no earlier than late 2010. By that point, I have no doubts that 5.3.2 will already be released, if not even 5.3.3 – in other words, it will be a fairly mature product.</p>

      <p>Currently, most Linux distributions are already offering 5.3 as the standard current version, as is Mac OSX. Since the distributions are already backing it, the hosting providers will not be long to follow – and many have already indicated that they are preparing for it.</p>

      <p>One way to get hosting providers to upgrade their offerings is through user pressure. Since ZF, Symfony, Doctrine, Agavi, and other projects are planning 5.3-specific offerings, there is already tremendous pressure from their respective communities directed at hosting providers – and this <em>will</em> have an effect.</p>

      <p>Finally, we plan to support the last minor release of the 1.X branch for a while following the 2.0 release, as we know that upgrading will not be something everyone can jump on board immediately – in part due to hosting providers. You do not have to adopt immediately.</p>

      1. Dec 18, 2009

        <p>Really, why so late? The whole host support question is completely unnecessary, exactly for the reason above: branching. If you are going to branch anyway, why not get 2.0 out there ASAP? People (like myself) are impatient for a namespaced ZF. Doctrine is releasing a first beta of their 2.0 in early January. Yes, Symfony is mentioning late 2010, but personally I do not care much about Symfony. But perhaps exactly <strong>because</strong> Symfony is being so slow about it, ZF has an opportunity to jump in that gap.</p>

        <p>Overall I simply don't see why it has to take a whole year. Adapting the current codebase to use namespaces really shouldn't take a year. That's just ridiculous. As soon as you establish the guidelines any twat can do it. I realise there are (some) other changes you would like to be included in the 2.0 release, but really, those can be in 2.1 as well, who cares, it is just a number. We have been waiting in anticipation for namespaces for a very long time, and now that they're finally here, and our IDEs finally support it, you're telling me I have to wait another whole year before I will be able to use a namespaced ZF. I beg of you to reconsider. Pretty pretty (pretty) please.</p>

        1. Dec 18, 2009

          <p>It's more than just namespacing that we're doing. We're re-architecting a number of components in order to make them (a) easier to maintain, and (b) more performant. That work will not happen overnight. At the same time, there are a ton of issues in the tracker that need to be addressed or at least considered (to ensure we don't propagate them to the new release, or to ensure requested features make it to the new release). Additionally, since major releases are the only times we can break backwards compatibility, we want to try and address as many such breaks as possible <em>now</em> so that we won't feel hampered 6-12 months down the road and have to wait another 2 years to change things. Finally, who do you think is going to do the work, exactly? Yes, we have 3 folks at Zend, myself and two others – but we have to work not only on this, but also maintaining the current branch, reviewing new code contributions, documentation, maintaining the site, and more. The community? Mostly volunteers, who have limited time individually to contribute. As an aggregate, yes, we can make progress – but it <em>will</em> take time.</p>

          <p>Doctrine started work on 2.0 close to a year ago – they are <em>proof</em> that a change like this won't happen overnight.</p>

          1. Dec 18, 2009

            <p>Well, Doctrine 2.0 does have a lot of changes other than namespacing as well. </p>

            <p>I'm am not saying that wont be a lot of work nor claiming you have massive human resources, I just said that looking at just namespaces, it should be possible to get that released early next year. I'll admit though, I hadn't thought of BC and the policy to only break it on major releases. And I wont deny some parts of ZF could use some BC breaking refactoring. I guess it would have been a good idea to start a little earlier, especially considering how long 5.3 has been in development, but there's nothing to be done about that now. It's indescribably disappointing though.</p>

            1. Dec 18, 2009

              <p>The 5.3 API did not stabilize until 2-3 months before the stable release. Since we were planning on taking advantage of a number of new language constructs, we needed to wait until they were stable to even begin planning (namespaces, for instance, underwent a number of iterations; additionally, some features like traits looked like they might make it into 5.3, but were dropped relatively late in the 5.3 cycle).</p>

              <p>Could we have started planning earlier? Potentially. But with initiatives like Zend_Tool, Zend_Application, and more, we were already overwhelmed with responsibilities.</p>

              <p>Frankly, I think it's probably just as well we wait. It's always good to wait until at least the .1 version of any release series to ensure the biggest bugs are worked out, and to get a chance to see how usage patterns pan out. We're much better prepared at this point to adopt 5.3 features than we would have been had we started planning earlier.</p>

              1. Dec 18, 2009

                <p>I was not going to make a big deal out of this, but since you shared your view on it, I'll do the same.</p>

                <p>It does not matter if the API was stable. It was in development, so it's not surprising that things changed along the way (although admittedly the last minute change did have larger implications than you would normally expect so late in development).</p>

                <p>What's more important is that you could have started with the BC breaking refactorings, in general, sooner. You know, those things that you are saying prevent you from putting a namespaced release out there early next year. Not because you've known how namespaces were going to work for a long time, because you didn't, but because you knew there was going to be a PHP release with namespaces. It doesn't require a lot of imagination to have the foresight to see that <strong>a lot</strong> of your userbase can not wait to use this feature.</p>

                <p>Are you telling me there was some conscious choice that favoured development of Zend_Tool and Zend_Application over preparing for 2.0? Because then you guys made a major error in judgement. Because in my humble opinion those additions really don't add any "much needed" functionality, but more importantly, addition of those do not break BC, thus could have been added <strong>after</strong> 2.0.</p>

                1. Dec 18, 2009

                  <p>Can we quit crying over spilled milk?</p>

                  1. Dec 18, 2009

                    <p>We can. I wasn't planing on furthering the discussion in this direction, that was just my response to Matthew's defense of the current time frame. I realize and mentioned there is nothing to be done about it now (aside from breaking with the BC policy perhaps), but I disagree that this was unavoidable as one would think by taking that reply word for word.</p>

                    <p>Perhaps a more interesting discussion would be what can be done to get to 2.0 as soon as possible, as in sooner than the currently projected release date of late 2010.</p>

                    1. Dec 18, 2009

                      <p>I am also really waiting for ZF 2.0 to come and I would love to get it as soon as possible. But what I don't want is when the requirement "to get it released asap" is getting more weight than all other requirements mentioned in the discussion and on this page. I rather wait another 12 months and get a production ready ZF 2.0 than have to wait maybe even a longer time to get ZF 2.1 or even 2.2 which fix all the problems that have been left in ZF 2.0 to release it asap.</p>

                      <p>12 months isn't really a long time nowadays.</p>

                      1. Dec 19, 2009

                        <p>I would agree, except for the 12 months is not a long time part. 12 months is an agonizing long time when you are waiting, and I already went through it waiting for PHP 5.3 to get to stable (on a side note I fail to see how 12 months has gotten any shorter).</p>

                        <p>That said, I think the main focus for 2.0 should be refactoring for flexibility, which allows you to tack on new behaviour to your hearts delight without breaking BC until 3.0. </p>

        2. Dec 18, 2009

          <p>I agree with Matthew on this. Everyone will have to wait for the established projects to implement their upgrade strategy.</p>

          <p>If you simply can't wait, consider new projects that are built from scratch on 5.3. I'm aware of one such framework project: <a href="http://li3.rad-dev.org/">Lithium</a></p>

          <p>And Matthew touched on a point about resource constraints. There always one good way a developer can help him with that problem. <ac:emoticon ac:name="wink" /></p>

          <p>,Wil</p>

          1. Dec 19, 2009

            <p>> "I agree with Matthew on this. Everyone will have to wait for the established projects to implement their upgrade strategy."</p>

            <p>The need for refactoring, the BC policy and namespaces did not drop out of the sky though. Anyway, lets drop this. Nothing to be done about it.</p>

            <p>Lithium is, if memory serves, a CakePHP fork. Just not for me. Also, I have my own resource constraints. Though maybe this <strong>is</strong> the ideal time for me to try and get some time available.</p>

  12. Dec 19, 2009

    <p>Honestly, I think the timing is spot on. All this talk of planning and implementing new features and refactoring for ZF 2.0 far earlier is sort of silly. PHP 5.3 is so new, and we have so many components, that until very recently there would have been a major shortage of developers with 5.3 experience. It's also completely moot - ZF 1.9.x and 1.10 work perfectly well under PHP 5.3 - nobody absolutely must have ZF 2.0 right now.</p>

    <p>>The need for refactoring, the BC policy and namespaces did not drop out of the sky though. Anyway, lets drop this. Nothing to be done about it.</p>

    <p>Your point? You expected us to cease all development for PHP 5.2, a version which will be supported for years to come and is everywhere, simply because PHP 5.3 might get widely adopted a year or two from now? We've known all this for a long long time - but I'd say most of us are still using PHP 5.2 in production. The will to improve ZF 1.x for our current production needs is still relevant. I won't be using 5.3 in production for a long time yet simply to let a few mini releases roll out with any loose issues resolved.</p>

    1. Dec 19, 2009

      <p>> "PHP 5.3 is so new, and we have so many components, that until very recently there would have been a major shortage of developers with 5.3 experience."</p>

      <p>Really, as I've mentioned before, nobody would have needed any 5.3 experience to implement the refactorings that are needed. The two (support for 5.3, namespaces in particular, and BC breaking refactoring) are completely separate, except in that implementing namespaces in itself is a BC breaking refactoring. I'll reiterate that I doubt I am the only one waiting for the opportunity to use the 5.3 features in production environments. If refactorings were further progressed, this would have been a reality many months earlier.</p>

      <p>> "You expected us to cease all development for PHP 5.2, a version which will be supported for years to come and is everywhere, simply because PHP 5.3 might get widely adopted a year or two from now?"</p>

      <p>No, of course not, that is ridiculous. I would have expected to start the BC breaking refactoring for 2.0 sooner. In a separate branch.</p>

      <p>However, I would like to add that I am not looking for scapegoating or anything like that. It is the way it is, and as much as you all can deny error on anyones part or acknowledge it, it does not effectively change anything right now. The continued defense of the current state of things is more a battle of egos than anything else IMO.</p>

      <p>> "It's also completely moot - ZF 1.9.x and 1.10 work perfectly well under PHP 5.3 - nobody absolutely must have ZF 2.0 right now."</p>

      <p>Maybe you can explain to me how not being an absolute requirement makes it moot? I can think of an endless list of things that I do not absolutely require, but make a major positive impact on development nonetheless. </p>

      1. Dec 19, 2009

        <p>>Really, as I've mentioned before, nobody would have needed any 5.3 experience to implement the refactorings that are needed.</p>

        <p>It's really hard to see how one could take advantage of PHP 5.3 without the necessary experience. Sure, you could hit the low hanging fruit but that is mere cosmetics and doesn't bring about significant advantages or improvements to the framework as a whole as the Roadmap is currently hinting at. Switching syntax a new major version does not make. The relevant refactorings depend on your view - there are dozens of components that could use improvement outside the MVC core. Without more resources, hitting all of them is very difficult.</p>

        <p>>No, of course not, that is ridiculous. I would have expected to start the BC breaking refactoring for 2.0 sooner. In a separate branch.</p>

        <p>I was hinting at the resource issue. Take myself - I could have a) worked on ZF 2.0 during 2009 or b) written Zend_Feed_Reader, Zend_Feed_Writer and Zend_Feed_Pubsubhubbub which I really wanted yesterday on my production platform which will run PHP 5.2 for at least another six months. I could not do both. The needs of the now will always be more pressing. We're only now hitting the point where those needs are starting to coincide with PHP 5.3.</p>

        <p>It is something of an ego battle <ac:emoticon ac:name="wink" />. People have worked their asses off for every single ZF minor version this year with some really amazing results applicable right now to improving their applications. Questioning why nobody was worked on ZF 2.0 misses a huge point - everything we've done IS an improvement for ZF 2.0. You've missed the indirect benefits of that. Zend_Application? Zend_Tool? Zend_Feed_XXX? Tons more. Throw in Matthew's MVC improvements (which he even has some code for) and you have a card of features that could already justify a ZF 2.0 release even without the PHP 5.3 improvements. Frankly I'm amazed at some of the stuff we've crammed into mere minor releases <ac:emoticon ac:name="wink" />. You should looks at how lines of code has increased month on month since the 1.0 release. That ZF 2.0 is an opportunity to allow PHP 5.3 as a dependency and break compatibility where needed shouldn't de-emphasis the fantastic work of the past year in making the framework better than ever with new features. I've always thought we passed the watermark for a notional ZF 2.0 months ago and we're really working towards ZF 3.0 <ac:emoticon ac:name="wink" />.</p>

        <p>> Maybe you can explain to me how not being an absolute requirement makes it moot?</p>

        <p>You could run ZF 1.10 on PHP 5.3 in production today. PHP 5.3 isn't the reason for ZF 2.0, it's merely another dependency we can leverage off. People overestimate the importance of PHP 5.3 to improving anything. If you have good code now, you'll still have good code on PHP 5.3. The reverse also holds true. An awful lot of improvements that can be made have nothing to do with the PHP version. This is the unfortunate consequence of having ZF 2.0 and PHP 5.3 so closely linked.</p>

        1. Dec 19, 2009

          <p>Padraic,</p>

          <p>You hit the nail on the head. The key to this discussion is exactly as you just put it:</p>

          <p>"People overestimate the importance of PHP 5.3 to improving anything."</p>

          <p>I guess now that PHP 5.3 exists at all anything written against PHP 5.2 is just an abomination right. Really, I mean, those who have reviewed the code behind 1.9+ (I do this for any code I'm going to use on large projects), don't you think it's pretty good even without 5.3?</p>

          <p>Sure, I want 5.3 and I want everything I use to support it, BUT ==>> <a href="http://framework.zend.com/issues/secure/IssueNavigator.jspa?status=Open">http://framework.zend.com/issues/secure/IssueNavigator.jspa?status=Open</a></p>

          <p>The time invested in discussing this moot issue could have been used to resolve a couple bug-hunt days issues. Every issue resolved now is going to make 2.0 that much better.</p>

          <p> Padraic, thanks for working on the very components that I use to get stuff done instead of jumping to 2.0 just because you thought it would be cool.</p>

        2. Dec 19, 2009

          <p>We'll agree to disagree. I don't use Zend_Feed nor Zend_Tool and didn't really need Zend_Application. In contrast, I am, and I am guessing a lot of users if not most, very eager to start using namespaces in ZF projects. From this perspective your priorities seem off. May be you're right though, and your userbase is more appreciative of before mentioned components than it would have been of a quick namespaced release. In which case I stand alone and acknowledge that this discussion is moot. But I seriously doubt it.</p>

          1. Dec 19, 2009

            <p>A quick namespaced release would never be ZF 2.0 since it's mere cosmetics if nothing deeper - if folk want namespaces that bad there's nothing stopping them from contributing a namespaced 1.10 release. I'm sure all of us would appreciate the help. I'll agree to disagree though <ac:emoticon ac:name="wink" />. I don't view namespaces as sufficient justification alone for a major release.</p>

  13. Jan 04, 2010

    <p>All the talk on the features and specs for ZF 2.0 are great but one thing I think was kind of forgotten about on the 1.0 release was the documentation. Now don't get me wrong I think we have great component documentation but one thing I think we could use more of is actual use case tutorials. Say someone wants to get Auth/Acl/Navigation setup on their website; why should we rely on them searching through a whole lot of blogs (outdated) which are possibly using bad practices? I think before we even start to approach the release date of ZF 2.0 we need to have more Getting Started and use case documentation written; and actually it's something I would like to help out with too.</p>

    1. Jan 05, 2010

      <p>This is already in the works. Please have a look at a test version of the 1.10 manual
      <a class="external-link" href="http://www.mikaelkael.fr/doczf/1.10/en/">http://www.mikaelkael.fr/doczf/1.10/en/</a></p>

      1. Jan 05, 2010

        <p>Thanks Ralf for the link.</p>

        <p>It would be nice if there would be possibility to add comments to the pages. It`s a great addition to manual. Take a look at php.net/manual where comments are sometimes even more valuable than the content of the manual page.</p>

        <p>Is there any chance to add this kind of feature or is it too late?</p>

        <p>BR,<br />
        Michal</p>

        1. Jan 05, 2010

          <p>This is in the works, and will hopefully be in place for the 1.10 release.</p>

  14. Jan 30, 2010

    <p>Just an idea for further refactoring of Exceptions.</p>

    <p>In Doctrine 2 we move all the exception messages to the exception class itself which makes "the real code" much more tidy, like:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    throw FormException::duplicateElementName($elementName);

    class FormException extends \Exception
    {
    static public function duplicateElementName($elementName)

    Unknown macro: { return new self("The element $elementName you specified is already registered!"); }

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

    <p>This way you can re-use exception messages more easily and get all the messages out of the code. Additionally its much easier to globally change exception message behaviour (in regards to error-codes for example).</p>

    1. Apr 23, 2010

      <p>Isn't this bringing some more complex development and creating usage errors?</p>

      <p>If these methods aren't well-documented, users may throw the wrong exceptions in the wrong place : there are a lot of peolple who are already confused with differences between exception classes <code>RuntimeException</code> and <code>LogicException</code>.</p>

  15. Feb 20, 2010

    <p>I would like a freely configurable user authentication module, which can be configured via an ini file. Optimally, this module should have the following features:</p>
    <ul>
    <li>Freely selectable database (at least in MySQL)</li>
    <li>Completed set of table definitions</li>
    <li>Possibility to deposit its own table definition as a set</li>
    <li>After creating a new user data to the user via e-mail will be sent</li>
    <li>After the confirmation of the new user's account will be unlocked</li>
    </ul>

    <p>The reason for my desire is that you need for almost any project, such a module. And it would just be cool if there would be this one (almost) ready-made solution that has to be just configured.</p>

    <p>Greetings,<br />
    trady </p>

  16. Feb 28, 2010

    <p>There are some classes names like "Zend_Config_Writer_Array" which can't simply renamed to "zend\config\writer\Array" because "Array" is a reserved word.</p>

    <p>The complete list:</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    find -name And.php -or -name Array.php -or -name Break.php \
    -or -name Case.php -or -name Catch.php -or -name Class.php \
    -or -name Clone.php -or -name Const.php -or -name Continue.php \
    -or -name Declare.php -or -name Default.php -or -name Do.php \
    -or -name Else.php -or -name Elseif.php -or -name Enddeclare.php \
    -or -name Endfor.php -or -name Endforeach.php -or -name Endif.php \
    -or -name Endswitch.php -or -name Endwhile.php -or -name Extends.php \
    -or -name Final.php -or -name For.php -or -name Foreach.php \
    -or -name Function.php -or -name Global.php -or -name Goto.php \
    -or -name Ff.php -or -name Implements.php -or -name Instanceof.php \
    -or -name Namespace.php -or -name New.php -or -name Or.php \
    -or -name Private.php -or -name Protected.php -or -name Public.php \
    -or -name Static.php -or -name Switch.php -or -name Throw.php \
    -or -name Try.php -or -name Use.php -or -name Var.php -or -name While.php \
    -or -name Xor
    ./Zend/Server/Reflection/Class.php
    ./Zend/Server/Reflection/Function.php
    ./Zend/Translate/Adapter/Array.php
    ./Zend/Controller/Router/Route/Static.php
    ./Zend/CodeGenerator/Php/Class.php
    ./Zend/Cache/Frontend/Class.php
    ./Zend/Cache/Frontend/Function.php
    ./Zend/Cache/Backend/Static.php
    ./Zend/Gdata/YouTube/Extension/Private.php
    ./Zend/Crypt/Rsa/Key/Private.php
    ./Zend/Crypt/Rsa/Key/Public.php
    ./Zend/XmlRpc/Value/Array.php
    ./Zend/Session/Namespace.php
    ./Zend/Ldap/Collection/Iterator/Default.php
    ./Zend/Ldap/Filter/And.php
    ./Zend/Ldap/Filter/Or.php
    ./Zend/Config/Writer/Array.php
    ./Zend/Search/Lucene/Search/Similarity/Default.php
    ./Zend/Search/Lucene/Search/Highlighter/Default.php
    ./Zend/Pdf/Cmap/ByteEncoding/Static.php
    ./Zend/Pdf/Element/Array.php
    ./Zend/Paginator/Adapter/Array.php
    ./Zend/InfoCard/Adapter/Default.php
    ./Zend/InfoCard/Xml/KeyInfo/Default.php
    ./Zend/Reflection/Class.php
    ./Zend/Reflection/Function.php
    ./Zend/Queue/Adapter/Array.php
    ]]></ac:plain-text-body></ac:macro>

    <p>How should these classes renamed ?<br />
    (For abstract classes & interfaces the new name is already defined)</p>

    <p>EDIT: formated find</p>

  17. Mar 28, 2010

    <p>I second (or fifth) the use of Doctrine with the release of Zend Framework 2. Like many others I have already integrated the latest stable release of Doctrine with ZF 1.7 - ZF 1.10. I can not recommend this move enough.</p>

  18. Apr 15, 2010

    <p>>I second (or fifth) the use of Doctrine with the release of Zend Framework 2.</p>

    <p>+1 One up! <br />
    Ship with a mature ORM that comes with a huge community already and provide a best practice example on how to use it within the new Zend MVC.</p>

    <p>" Blog it! Post it! Comment it! We need to get Doctrine <a class="external-link" href="http://bit.ly/1FH5A9">http://bit.ly/1FH5A9</a> with the release of Zend Framework 2. <a class="external-link" href="http://bit.ly/29LHxZ">http://bit.ly/29LHxZ</a> " <a class="external-link" href="http://twitter.com/framework_zend/status/12256250204">http://twitter.com/framework_zend/status/12256250204</a></p>

    1. Dec 10, 2010

      <p>I would like to see Doctrine-like functionality within Zend Framework 2.0, and possibly a Doctrine adapter. I'm not sure if the others are suggesting the inclusion of the actual Doctrine library within ZF2, but I would think that would be off-limits - just as we do not expect to see MySQL or memcached bundled in.</p>

      1. Dec 19, 2010

        <p>Please discuss here, this page is "old"<br />
        <a href="http://framework.zend.com/wiki/display/ZFDEV2/Zend+Framework+2.0+Requirements">ZF 2.0 requirements</a></p>