A Simple Resource Injector for ZF Action Controllers

Matthew Weier O’Phinney writes a very useful article about resource injection; Brandon Savage approached me with an interesting issue regarding ZF bootstrap resources, and accessing them in your action controllers. Basically, he’d like to see any resource initialized by the bootstrap immediately available as simply a public member of his action controller.

So, for instance, if you were using the “DB” resource in your application, your controller could access it via $this->db.

I quickly drafted up a proof of concept for him using an action helper:


class My_ResourceInjector extends Zend_Controller_Action_Helper_Abstract
{
protected $_resources;

public function __construct(array $resources = array())
{
$this->_resources = $resources;
}

public function preDispatch()
{
$bootstrap = $this->getBootstrap();
$controller = $this->getActionController();
foreach ($this->_resources as $name) {
if ($bootstrap->hasResource($name)) {
$controller->$name = $bootstrap->getResource($name);
}
}
}

public function getBootstrap()
{
return $this->getFrontController()->getParam('bootstrap');
}
}

In this action helper, you would specify the specific resources you want injected via the $_resources property – which would be values you pass in. Each resource name would then be checked against those available in the bootstrap, and, if found, injected into the action controller as a property of the same name.

You would initialize it in your bootstrap:


class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initResourceInjector()
{
Zend_Controller_Action_HelperBroker::addHelper(
new My_ResourceInjector(array(
'db',
'layout',
'navigation',
));
);
}
}

The above would map three resources: “db”, “layout”, and “navigation”. This means you can refer to them directly as properties in your controllers:


class FooController extends Zend_Controller_Action
{
public function barAction()
{
$this->layout->disableLayout();
$model = $this->getModel();
$model->setDbAdapter($this->db);
$this->view->assign(
'model' => $this->model,
'navigation' => $this->navigation,
);
}

// ...
}

This approach leads to some nice brevity — you no longer need to fetch the bootstrap from the instantiation arguments, and then fetch the resource.

I thought about it some more, and realized that there’s a few problems: How do you know what is being injected from within the controller? How do you control what is being injected.

So, I revised it to pull the expected dependencies from the action controller itself…

Read the complete article here A Simple Resource Injector for ZF Action Controllers.

Updated Zend_Dojo_View_Helper_Dialog

Charles Kyle Spraggs writes; I’ve been tinkering around with view helpers quite a bit now and I realized that a lot of what I did in the Dialog could be done much easier by extending the DijitContainer view helper. So, I rewrote the dialog view helper to extend DijitContainer and moved Zend_Dojo_View_Helper_Dijit_Extended to Zend_Dojo_View_Helper_Dojo_Extended because the methods are meant to be used statically similar to Zend_Dojo_View_Helper::setUseDeclarative(). For those of you that have no idea what I’m talking about you should read Zend_Dojo_View_Helper_Dialog first.

New code!

Zend_Dojo_View_Helper_Dojo_Extended

This little puppy exists for the sole purpose of adding stylesheets based on the set dojo path (local/CDN) and version (if CDN).

Usage

// Code from Zend_Dojo_View_Helper_Dialog which adds the stylesheet for enhanced dialogs
Zend_Dojo_View_Helper_Dojo_Extended::addStylesheet('/dojox/widget/Dialog/Dialog.css');

more at SpiffyJr’s Blogaroo.

Zend Framework MVC Request Lifecycle

Kevin Schroeder writes an excellent article about the MVC lifecycle thats a must read for anyone even thinking about writing ZF plugins; Matthew wrote up an article on modules in Zend_Application and that got me thinking a little bit. When I have done training for Zend Framework, one of the things that mystifies students to some extent is the whole plugin architecture and where things can go. There has been several articles written about it, but they tend to use code to describe it. I was only able to find a small handfull of articles that used some kind of chart to describe what goes on. Not that that’s a problem, but I had found that when I drew out the request lifecycle that it helped the students understand it better.

The chart on the right is a color-coded chart that shows when something is executed and where it is executed from. This chart is intentionally missing a whole bunch of things for the purpose of simplicity. If you want a more full explanation of the request lifecycle…

Read full story Friday Framework Highlight: Zend Framework MVC Request Lifecycle

Writing Composite Zend_Form Elements

Jon Lebensold writes; This video should help you build your own composite Zend_Form element. We’ll be building a phone element. The phone element will have 3 textboxes, one for geographic location, area code and local code. In the following videos will add a custom cell phone validator and some ajax validation.

Grab a copy of the project or browse the repository.

View the Screen cast: Writing Composite Zend_Form Elements

Tab Container Enabled Forms

Nathan Garlington wrote a nice solution for Tab based forms; Yes, it is possible to display a form in a tabContainer. I do it all the time, including using other dijit containers as well. keep in mind that this is just my solution…there are probably other ways to do this. Feel free to customize it according to your needs. Also, you may notice that I don’t include an action attrib or method attrib declaration to the form node itself…this is because I handle form submitting via xhr. Example code below:


class My_Form extends Zend_Dojo_Form
{
public function init()
{
$this->setDisableLoadDefaultDecorators(true);

// setup the our default decorators
$this->setDecorators(array(
'FormElements',
array('TabContainer', array(
'id' => 'myTabContainer',
'style' => 'width: 950px; height: 420px;',
'dijitParams' => array('tabPosition' => 'top'),
)),
'DijitForm',
));

$this->setName('myAddTrailerForm');

$this->setElementDecorators(array(
array('DijitElement'),
array('Description'),
array('HtmlTag', array('tag' => 'dd')),
array('Label', array('tag' => 'dt')),
));

//call custom class methods to add form members
$this->_addElements()
->_addDisplayGroups();

}

private function _addElements()
{
$this->addElements(array(

// general information display group elements
new Zend_Dojo_Form_Element_FilteringSelect('field1', array(
'label' => 'First Field:',
'multiOptions' =>(array(
'option1' => 'option1',
'option2' => 'option2'
)),
'required' => true,
)),

new Zend_Dojo_Form_Element_CheckBox('cb1', array(
'label' => 'Are you sure?:',
)),

new Zend_Dojo_Form_Element_FilteringSelect('year', array(
'label' => 'Year:',
'multiOptions' => array(/*....*/),
'required' => true,
)),

new Zend_Dojo_Form_Element_ComboBox('comboBox1', array(
'label' => 'ComboBox1:',
'multiOptions' => array(/*....*/),
'required' => true,
'autocomplete' => false,
'attribs' => (array('propercase' => true, 'trim' =>true)),
)),

new Zend_Dojo_Form_Element_ValidationTextBox('validationBox1', array(
'label' => 'ValidationBox1:',
'required' => true,
'attribs' => array('uppercase' => true, 'trim' =>true),
)),

new Zend_Dojo_Form_Element_ValidationTextBox('validationBox2', array(
'label' => 'ValidationBox2:',
'required' => true,
'invalidMessage' => "Please enter a value",
'attribs' => array('maxlength' => 17, 'uppercase' => true, 'trim' =>true),
'filters' => array('StringToUpper'),
'validators' => array('Alnum'),
)),
)); // end $this->addElements

return $this;
} // end _addElements()

/**
* Create the tabbed container layout
*/
private function _addDisplayGroups()
{

// add the display groups
$this->addDisplayGroup(
array( // elements in the displayGroup
'field1',
'cb1'
),
'generalInformation' // displayGroupName
);

$this->generalInformation->setDecorators(array(
'FormElements',
array('HtmlTag', array('tag' => 'dl')),
array(
'ContentPane', array(
'title' => 'General Information'
)
)
));

$this->addDisplayGroup(
array(
'year',
'comboBox1',
),
'tab2'
);

$this->tab2->setDecorators(array(
'FormElements',
array('HtmlTag', array('tag' => 'dl'),
array(
'ContentPane', array(
'title' => 'Tab 2'
)
)
));

$this->addDisplayGroup(
array(
'validationBox1',
'validationBox2',
),
'tab2'
);

$this->tab2->setDecorators(array(
'FormElements',
array('HtmlTag', array('tag' => 'dl', 'class' => 'addTrailer')),
array(
'ContentPane', array(
'title' => 'Axles'
)
)
));

return $this;
} // end _addDisplayGroups();

public function buttonsSubForm()
{
$subForm = new Zend_Dojo_Form_SubForm();
$subForm->setDecorators(array(
'FormElements',
array('HtmlTag', array('tag' => 'div', 'id' => 'buttonsSubForm', 'class' => 'span-7 push-3 prepend-top')),
))
->setElementDecorators(array(
array('DijitElement'),
))
->addElements(array(
new Zend_Dojo_Form_Element_Button('submit', array(
'type' => 'button',
'label' => 'Submit it!',
'attribs' => array('disabled' => 'disabled'),
)),

new Zend_Dojo_Form_Element_Button('cancel', array(
'label' => 'Cancel',
)),
));
$subForm->submit->removeDecorator('DtDdWrapper');
$subForm->cancel->removeDecorator('DtDdWrapper');
return $subForm;
} // end buttonsSubForm();
} // end class

That’s it. There may be some errors in there, but the idea is there. As you can see, once you see you how it goes together, it’s actually trivial to add dijit layout containers to a zend form. Be sure that you are in fact extending Zend_Dojo_Form, or using one of the other methods shown in the docs for dojo-enabling your form. You may or may not like the buttons subForm I use here either…I do this because otherwise the submit buttons have to be in their own tab, and that makes it confusing for some of my users…they don’t know where the buttons are to submit the form. So I display them in a div that renders outside the tab container, disable the submit button, and using dojo’s methods, I enable the button on the onValidStateChange dojo event. Let me know if you have any questions!

regards,
Nathan Garlington

Connecting Flex 4 and RESTful Web Services using Zend Framework

David Flatley writes;

With Adobe’s latest incarnation of the Flex Framework and the Flash Builder integrated development environment (IDE), creating truly engaging front-end clients is now more streamlined. Some of the useful tools and features covered in this article are the Data/Services, Test Operation, and Network Monitor additions to Flash Builder. In this article, I explain how to set up a simple Representational State Transfer (REST) service using the Zend Framework 1.9 locally and connect to it in the Flex 4 application.

To get the most from this article, you should have a basic knowledge of the Zend Framework version 1.9. Development experience locally on your machine with Apache Server distributions like XAMPP, WAMP, or MAMP is helpful but not mandatory. You will need to deploy the server-side application on Apache running PHP. There is no database connectivity for this article.

Finally, you must have Flash Builder with PHP development tools installed or some flavor of the Eclipse IDE with the Flash Builder plug-in to complete the examples in this article.

Read the Full Story.

Easy command line scripts with Zend Application

David Caunt wrote up a useful article on command line scripting;

As PHP developers, it is convenient to be able to write command line scripts in PHP. In doing so, you will almost certainly want access to Zend Framework components and their configurations as if you are writing a normal MVC app, but without invoking the MVC stack and without loading unnecessary resources. I’ve seen solutions where actions are exposed as controller actions and called by wget – these are counter-intuitive, inefficient, and will suffer from max execution timeouts and other problems.

Zend_Applicaton to the rescue

Lets start with our website’s public/index.php – the script which sets up and launches an application. It looks roughly like this:

full article here; Easy command line scripts with Zend Application.

Zend_Form Decorators Explained

Jon Lebensold posts another great screen cast about one of the most confusing parts of Zend Framework ever created 🙂 ;

One of the pain points for folks who are starting to work with the Zend Framework is the Decorating functionality found in the depths of Zend_Form. I’ve witnessed countless instances when a developer becomes excited by Zend_Form’s easy-to-implement form validation and creation, only to become frustrated by countless hours of fighting with Zend_Form_Decorators. This video is a humble attempt on my part to walk through how Zend_Form Decorators work and how you can reason your way through a desire result. I couldn’t have gotten my own head around this implementation of the decorator pattern without Matthew Weier O’Phinney’s excellent posts and his original devzone article.

UPDATE: check out this blog post / tutorial for ZF 1.10.0: http://framework.zend.com/manual/en/learning.form.decorators.html

I’ll show you a bit about how Zend_Form_Decorators are constructed and how to take the default zend_form layout and transform it into a table.

Grab a copy of the project or browse the repository.

via Zendcasts.

Zend_Translate with Dynamic Parameters

Pascal Opitz posted a nice little snippet; Just a quick snippet to have dynamic parameters in the underscore function, without having to write sprintf every time.

<?php
class Translate extends Zend_Translate {
  public function _() {
    $args = func_get_args();
    $num = func_num_args();

    $adapter = $this->getAdapter();

    $args[0] = $adapter->_($args[0]);

    if($num <= 1) {
      return $args[0];
    }
    return call_user_func_array('sprintf', $args);
  }
}

Usage would be something like the following:

$t = new Translate('array', $array_translation, $lang);
echo $t->_('My name is %s', 'Pascal');
echo $t->_('I have a %s and a %s', 'Cat', 'Horse');

Note: The above little snippet solves one of the major gripes I have with the default _() function.

via Zend_Translate with dynamic parameters.