ZF Blog

2011-09-26 Dev status update

Zend Framework status update for the weeks of 13 - 26 September 2011.

2011-09-14 IRC Meeting

We held our third IRC meeting on Wednesday, 14 September 2011. On the agenda were:

  • RFC on configuration
  • Where components falling outside the standard distribution should live if incomplete
  • Goals of the Module Manager
  • Directory structure for modules

Configuration

Between the competing RFCs on configuration, the IRC discussion, and some back-and-forth following the meeting, the following summarizes the current consensus on how ZF2 will deal with component configuration:

  • Hard dependencies that do not have sane defaults would be in the constructor signature
  • The last argument in the constructor signature would be optional, and expect an instance of the component's Options class
  • If a dependency has a sane default, we would not include an argument in the constructor, but would allow setter injection (which could be automated by the DI container)
  • The component's Options class would handle optional configuration arguments, and provide validation for those arguments.
  • The component would directly access optional arguments from the Options instance it composes

Note the word "Options". In discussions, we decided we should call this functionality "Options" as it denotes that the values are optional, and also to prevent nomenclature conflicts with the already existing Zend\Config component. We will be producing a poll on the wiki to do a final vote very soon.

Unfinished "Extras" components

The discussion centered around whether or not we would remove unrefactored components that fall outside the standard distribution -- things like service components that have not been converted to namespaces, updated to latest exceptions practices, and not refactored to use the new HTTP functionality.

Only slight debate erupted -- the decision is:

  • Keep this functionality in the master branch
  • Add an annotation such as "@incomplete" to the file and/or class-level docblocks.
  • Add the "@incomplete" annotation to related test classes, and add a rule to phpunit.xml to skip such tests.
  • Comment out sections in the manual referring to these components.

We will then add rules to packaging to omit such classes and resources.

Module Manager Goals

The Module Manager is a component for scanning and initializing modules during application bootstrapping. As such, it's fairly central to the new MVC approach, and we wanted to be sure we captured its goals. A sizable list of goals was presented, and we voted on each. There are too many to relate here, so instead I'll simply link you to the summary.

Most items were straight-forward, but there are a few conflicting ideas about what the scope of the manager; should it simply act as a kernel for bootstrapping, or have deep ties within the application?

Current development of this tool has taken the former approach, but has exposed a number of useful features that allow a ton of flexibility for a variety of approaches. One, in particular, is a method getLoadedModules(), which returns an associative array of module name/module objects. With this, I was able to do such things as loop through modules, check for the existence of specific methods, and then call them to do things such as event listener registration.

Module Directory Structure

By the time of the meeting, we already had a couple different module directory structures floating around, and the discussion centered on which one to use. Except that several people brought up one very, very good point: with a well-known class (the module's "Module" class) that we're querying, the structure doesn't matter, and does not need to be enforced.

As such, our decision was that we should have a recommended structure that satisfies the various use cases we originally brainstormed. Among these:

  • Ability to serve multiple namespaces (if desired)
  • Separation of code from non-code assets, if provided (such as CSS, JS, HTML)
  • Separation of view templates, if provided, from code
  • Separation of configuration, if provided, from code

As such, the following structure was generally agreed upon as a recommendation:

modules/
    SpinDoctor/
        Module.php
        autoload_classmap.php
        autoload_function.php
        autoload_register.php
        configs/
            module.config.php
            routes.config.ini
        public/
            images/
            css/
                spin-doctor.css
            js/
                spin-doctor.js
        src/
            SpinDoctor/
                Controller/
                    SpinDoctorController.php
                    DiscJockeyController.php
                Form/
                    Request.php
        tests/
            bootstrap.php
            phpunit.xml
            SpinDoctor/
                Controller/
                    SpinDoctorControllerTest.php
                    DiscJockeyControllerTest.php
        views/
            spin-doctor/
                album.phtml
            disc-jockey/
                turntable.phtml

Public assets such as images, CSS, and JS could either be symlinked into the public tree, copied, or managed by an asset manager such as Assetic.

Regarding the various autoload_*.php files, these were brought up in a post from Ralph, based on discussions he and I have had. The idea behind these is that we can satisfy several typical use cases for modules:

  • Download and use: simply require 'autoload_register.php'; and start using classes.
  • Use with custom registration: spl_autoload_register(include 'autoload_function.php');, which allows you to specify to spl_autoload_register whether or not to append or prepend the function to your autoloader stack.
  • Custom autoloading class map: aggregate the returns of autoload_classmap.php into a single classmap for your application.

There's still some discussion going around these files, but they've been adopted in the prototypes at this time.

MVC Prototype Status

The MVC prototype has grown tremendously, in large part due to the efforts of Evan Coury and his work on the Module Manager. The module manager now does the following:

  • Aggregates configuration from all modules
    • Including modules provided as phars!
  • Provides introspection and access to discovered modules
  • Optionally allows configuration caching

The MVC prototype has also grown. Based on a suggestion from Greg N. on the mailing lists, the EventManager was refactored slightly to do the following:

  • Removed references to "handlers" in favor of "listeners" to provide a consistent terminology (both internally as well as with other systems of similar design)
  • trigger now allows passing an Event object for any one of its required arguments. This allows creation of custom Event objects, as well as re-use of them.
  • trigger was modified to allow an optional final argument, either the fourth argument or an argument following an Event object: a callback that indicates whether or not to halt execution. This largely eliminates the need for triggerUntil at this time.
  • Locally attached listeners are now combined with static listeners into a single priority queue when trigger is called. This provides a consistent expectation, and allows you to register static listeners that can be called prior to those attached locally.

What the above allowed was the ability to move routing and dispatching into listeners within Zend\Mvc\Application, using a custom MvcEvent object. The upshot is:

  • Simpler code
  • Accessors for well-known (and/or expected) objects (e.g., getRequest(), getRouteMatch(), getResult())
  • Events are registered with priority in order to shape the execution workflow
  • The ability to replace the default routing and dispatch listeners with custom listeners.

This last point allowed me to prototype a ZF1-emulation layer in the new ZF2 paradigm. This effort was surprisingly easy, and helped illustrate how flexible the prototype can be.

Additional work on the MVC centered around error handling, and providing a simple mechanism for discovering and handling errors. The zf-quickstart example showed that this largely eliminates the need for an ErrorController.

At this time, we're quickly closing in on what the MVC will likely look like for ZF2, and hope to merge the ZendMvc and ZendModule modules into the library very soon.

DI Annotation Support

Ralph has been refactoring the Reflection, CodeGenerator, and Code\Scanner components to follow a consistent API, and to live under a common tree, Zend\Code. Part of this work is to also provide a parser/tokenizer for PHP docblocks, with the goal of providing annotation support to components that need it. In particular, this could assist the Dependency Injection component, allowing more intelligent hinting as to what setters are required and/or the specific arguments to inject. Another potential use might be with modules, to indicate what they provide and/or methods that should be called at initialization.

This work should hit master this week, and will be compatible with the docblock extension.

Cloud Infrastructure

Enrico has been working on updating the Amazon, Rackspace, and GoGrid services to use the new HTTP functionality. In doing so, he's discovered areas where the HTTP component needed improvement, as well as places he could better test. At this time, all changes he's done are incorporated in the master branch, with the exception of some tests for GoGrid.

This work has helped round out a new offering in Zend Framework, as well as to test recent development work and ideas such as the HTTP component and the Options proposal.

The Future

There are new RFCs and discussions erupting regularly on the mailing list and in the #zftalk.2 IRC channel on Freenode; I encourage you to subscribe to the former and join in the latter so that you can participate.

Also, we have an IRC meeting this week, 28 September 2011 at 17:00 UTC. The agenda is online, but could potentially use some more topics and votes. Talk to you Wednesday!

Return to entries

blog comments powered by Disqus