ZF Blog

2011-10-10 Dev status update

Status update for the weeks of 27 September - 10 October 2011.

2011-09-28 IRC Meeting

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

  • Discussion of a Doctrine Bridge
  • Discussion of the Standard Distribution
  • Roadmap

The meeting has been summarized previously. The tl;dr for those who don't want to click through on the link:

  • Everyone agrees we'd like a Doctrine Bridge; it's up to somebody to get something concrete rolling.
  • The Standard Distribution was previously defined; however, additions will be considered on a case-by-case basis.
  • Expect beta 1 to drop during ZendCon.

Development Notes

View Convenience API

After a prolonged discussion, I worked on a "View Convenience API". The goal was to simplify view usage and syntax.

The end result is a syntax very much like ZF1, but more performant under the hood, and with easier ways to get at the various helper objects. Per a suggestion (and pull request!) from Rob Allen, we now extract view variables prior to rendering the view script. Since the Variables container returns escaped versions of variables by default, this makes for very succinct syntax. You may also access variables using property overloading (e.g., $this->foo), via a get() method, or by accessing the Variables container directly. Additionally, you can now access the unescaped values using a new raw() method in the renderer.

Helpers can now be accessed via method overloading, as they were in ZF1. The following will occur:

  • If the helper is invocable (i.e., a functor, implementing the __invoke() magic method), it will be invoked with any arguments passed.
  • If not invocable, the helper instance will be returned.

Additionally, an "escape" view helper was created. This is composed into the Variables container by default, and allows specifying alternate callbacks and encoding when desired.


<?php $this->headTitle($title?>
<h2><?= $title ?></h2>
<ul>
<?php foreach ($entries as $entry): ?>
    <li><?= $this->escape($entry->getName()) ?></li>
<?php endforeach ?>
</ul>

tl;dr: The view layer is fun again!

Controller Convenience API

Following a couple short threads about a controller convenience API, I implemented a few new features in the MVC controller layer:

  • Controllers may be optionally "event injectible". If they are, they will be injected with the MvcEvent used in the Application object. This allows it to be tied more closely into the full request cycle.
  • Controllers may be optionally "locator aware". If they implement the LocatorAware interface, they will be injected with the DI container or Service Locator attached to the Application. This can be used to pull out optional dependencies.
  • We've created a controller-layer plugin broker, analagous to ZF1's "action helper" system. The idea behind this is to provide re-usable functionality for controllers in a light-weight fashion. Unlike ZF1, these plugins will not be workflow-aware, and will only optionally be injected with the current controller (based on presence of a setController() method).
  • You can access controller plugins via method overloading. Unlike view helpers, method overloading only ever returns the plugin instance.

So, in a nutshell:


<?php
class FooController extends ActionController
{
    public function 
processAction()
    {
        
// Locator-awareness for pulling conditional functionality:
        
$form $this->getLocator()->get('foo-form');
        
        
$post $this->getRequest()->post()->toArray();
        if (
$form->isValid($post)) {
            
// do some processing
            // Redirection via a plugin:
            
return $this->redirect()->toRoute('foo-success');
        }
    }
}

Working controller plugins now include:

  • Url (generates URLs from a configured router)
  • Redirect (updates the Response object with a redirect status code an Location header; Location URL can be either a static URL or generated from the router)
  • FlashMessenger (session-based flash messages)
  • Forward (dispatch an additional controller)

The last plugin enables users to dispatch an additional controller -- without requiring a dispatch loop within the Application::run() logic! It does, however, require that the controller calling it be defined as LocatorAware, so that it can obtain the configured controller instance.

tl;dr: The Controller layer is getting a lot of good functionality.

Zend\Code refactoring

Ralph worked for several weeks on a refactoring of the Zend\Code component. Part of this was moving Reflection and CodeGenerator under that tree, as well as ensuring the APIs were consistent across all three components (as Zend\Code also contains the Scanner component). This work was merged on 6 October 2011.

Part of this update also included a comprehensive annotations parser. This allows us to now scan docblocks for annotations and represent them as objects, giving rise to a number of potential new workflows for ZF2.

DI Updates

One key driver behind annotations support was to allow using annotations to hint to the DI Compiler how to create definitions. Additionally, work was done to allow creating definitions via configuration. This allows things like:


<?php
use Zend\Di\Definition\Annotation as Di;

class 
Foo
{
    
/**
     * @Di\Inject()
     */
    
public function setEvents(EventCollection $events)
    {
    }
}

which will inform the DI container that this method should be injected at construction. Additionally, you can now do things like this:


<?php
$config
['di'] = array(
'definition' => array('class' => array(
    
'Mongo' => array(
        
'__construct' => array(
            
'server'  => array(
                
'required' => false,
                
'type'     => false,
            ),
            
'options' => array('required' => false),
        ),
    ),
    
'MongoDB' => array(
        
'__construct' => array(
            
'conn' => array(
                
'required' => true,
                
'type'     => 'Mongo',
            ),
            
'name' => array(
                
'required' => true
                
'type'     => false,
            ),
        ),
    ),
    
'MongoCollection' => array(
        
'__construct' => array(
            
'db' => array(
                
'required' => true,
                
'type'     => 'MongoDB',
            ),
            
'name' => array(
                
'required' => true
                
'type'     => false,
            ),
        ),
    ),
    
'Blog\EntryResource' => array(
        
'setCollectionClass' => array(
            
'class' => array(
                
'required' => false,
                
'type'     => false,
            ),
        ),
    ),
)),
'instance' => array(
    
'Mongo' => array('parameters' => array(
        
'server'  => 'mongodb://localhost:27017',
    )),
 
    
'MongoDB' => array( 'parameters' => array(
        
'conn' => 'Mongo',
        
'name' => 'myblogdb',
    )),
 
    
'MongoCollection' => array('parameters' => array(
        
'db'   => 'MongoDB',
        
'name' => 'entries',
    )),
 
    
'Blog\EntryResource' => array('parameters' => array(
        
'dataSource' => 'CommonResource\DataSource\Mongo',
        
'class'      => 'CommonResource\Resource\MongoCollection',
    )),
 
    
'CommonResource\DataSource\Mongo' => array('parameters' => array(
        
'connection' => 'MongoCollection',
    )),
));

The above will ensure that we use the provided scalar values for injection in the various constructors and setters in the definition, and still allows for object injection when required (e.g., conn, db, dataSource, connection).

tl;dr: DI has become incredibly flexible and powerful!

Cloud Infrastructure

Enrico managed to finish testing all Zend\Cloud\Infrastructure functionality, with both online and offline tests! This gives us great confidence in the components (plural, as all infrastructure services also have related components under Zend\Service), and makes for a great new feature in ZF2. Enrico also backported the Infrastructure component to ZF1's trunk, in anticipation of an additional release on the ZF1 tree in the future.

CLI Module

Robert Basic wrote to the list about a prototype CLI module. The basic idea is to leverage the module architecture for executing CLI requests; routing would be performed utilizing Zend\Console\Getopt instead of the MVC router. Additionally, it would provide functionality for colorizing output. Overall, a solid beginning to a potential new console component!

Presentations

Both Rob Allen and Robert Basic gave presentations during the weekend of 7 - 9 October 2011, with Robert Basic giving a general overview session on ZF2 at Webkonf and Rob Allen giving a full day tutorial at PHPNW. Rob Allen's slides may be viewed online.

The Future

We have an IRC meeting this coming Wednesday, 12 Oct 2011; please post topics and/or vote on those already posted -- and make sure you're in attendance for the discussions!

Also, we'll be tagging beta1 this week, in preparation for a release during ZendCon next week. If you have feedback on the MVC or DI, please let us know ASAP!

Return to entries

blog comments powered by Disqus