I find that awefully wasteful for something which is automated...
The key here is that it's automated, and any level of automaton-type methods in the ZF are largely under a public or protected access. This has been discussed in detail on the ZF mailing list and having one action per class (Command Pattern) is quite simple to implement by subclassing the default Router. I'd say knowing the Router code for the ZF (and likely any framework) and how to change it is extremely useful since being stuck with the one routing strategy does not suit everyone.
Are there any instances where one might want a base action controller which would be later derived from - in which case requiring OOP? Specific examples please...
Yes, I highly recommend subclassing Zend_Controller_Action as a minimum for each and every application. The subclass can then use the init() method to append additional setup logic. I use it to inject a list of objects from the FrontController (See Zend_Controller_Front::setParam() ) into the ActionController easily without resorting to a Registry class which can get unwieldy (as well as messy) once overused in too many controller files. I'm sure you can find lots more uses for implementing additional plugin hooks and anything that strikes your fancy. I even subclass Zend_View since I prefer my output escaping to automated (ZF leaves it a developer level decision).
Here's one I have open in my editor for an open source project using ZF's subversion HEAD:
Bootstrap (index.php extract):
Code: Select all
$controller = Zend_Controller_Front::getInstance();
/*
* Create filters and pass to Controller
* This will disable the GET/POST superglobals
* and force access through the filter object
*/
if(isset($_POST) and !empty($_POST))
{
$controller->setParam('post', new Zend_Filter_Input($_POST));
}
if(isset($_GET) and !empty($_GET))
{
$controller->setParam('get', new Zend_Filter_Input($_GET));
}
/*
* Add other common objects to be
* passed to Controller.
*/
$controller ->setParam('view', $view)
->setParam('session', $session)
->setParam('registry', $registry)
->setParam('cache', $cache)
->setParam('dao', $dao);
$controller->returnResponse(true);
$response = $controller
->setControllerDirectory('./application/controllers')
->setRouter($router)
->setBaseUrl($base_url)
->dispatch();
/*
* By default Exceptions are not displayed.
* That won't do during development.
* Remove this in a live environment!
*/
$response->renderExceptions(true);
/*
* Echo the response (with headers) to client.
* Zend_Controller_Response_Http implements
* __toString().
*/
echo $response;
The Zend_Controller_Action subclass:
Code: Select all
class Astrum_Controller_Action extends Zend_Controller_Action
{
protected $_view = null;
protected $_get = null;
protected $_post = null;
protected $_session = null;
protected $_registry = null;
protected $_cache = null;
/**
* Initialise the custom Controller and
* assign variables for use in Action methods.
*/
public function init()
{
if($this->getInvokeArg('post'))
{
$this->_post = $this->getInvokeArg('post');
}
if($this->getInvokeArg('get'))
{
$this->_get = $this->getInvokeArg('get');
}
$this->_view = $this->getInvokeArg('view');
$this->_session = $this->getInvokeArg('session');
$this->_registry = $this->getInvokeArg('registry');
$this->_cache = $this->getInvokeArg('cache');
/*
* Additional settings for View
*/
$this->_view->URLROOT = $this->getRequest()->getBaseUrl();
$this->_view->setRegistry($this->_registry);
}
public function __call($funcname, $args = array()) // if an action method does not exist, forward back to index
{
$this->_forward('index', 'index');
}
}
This way only the controller action which is actually going to be used/executed get's parsed.
If you're not using OOP then why ask OOP questions? Functions can be used in the same way as controllers/actions. But with functions it becomes a more complex challenge when you need to push your separated concerns (view, input filtering, sessions, etc.) into that function for use. I think the OOP variant is a good deal easier and would require a lot less setup code since it's easily centralised in a single subclass (see above) with all the OOP advantages using a class entails.