I'm building a project on top of the ZF (how better to learn it). Notably I use the current SVN and the incubator components, so what I have is strictly for the revised MVC components. The current basic Zend_Controller_Action subclass I added:
Code: Select all
<?php
/**
* LICENSE
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to Astrum@Astrum.com so we can send you a copy immediately.
*
* @category Astrum
* @package Astrum_Controller
* @copyright Copyright (c) 2006 Pádraic Brady (http://blog.quantum-star.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/
/** Astrum_Controller_Action_Exception */
require_once 'Astrum/Controller/Action/Exception.php';
/** Zend_Controller_Action **/
require_once 'Zend/Controller/Action.php';
/**
* Extends Zend_Controller_Action for custom Action tasks and setup.
*
* @category Astrum
* @package Astrum_Controller
* @copyright Copyright (c) 2006 Pádraic Brady (http://blog.quantum-star.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/
class Astrum_Controller_Action extends Zend_Controller_Action
{
/**
* Holds a Zend_View object.
*
* @var Zend_View
*/
protected $_view = null;
/**
* Holds a Zend_Session object.
*
* @var Zend_Session
*/
protected $_session = null;
/**
* Holds a Zend_Registry object.
*
* @var Zend_Registry
*/
protected $_registry = null;
/**
* Holds a Zend_Filter_Input object encapsulating $_POST.
*
* @var Zend_Filter_Input
*/
protected $_post = null;
/**
* Holds a Zend_Filter_Input object encapsulating $_GET.
*
* @var Zend_Filter_Input
*/
protected $_get = null;
/**
* Initialise the custom Controller and
* assign variables for use in Action methods.
*
* @return none
* @access public
*/
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');
/*
* Additional settings for View
*/
$this->_view->URLROOT = $this->getRequest()->getBaseUrl();
}
}
Here's what my current (damn messy!) bootstrap index.php file looks like:
Code: Select all
<?php
/**
* Bootstrap file for Astrum Futura
*
* For current SVN of the Zend Framework.
*/
/*
* The basics...
*/
error_reporting(E_ALL);
ini_set('display_errors', 1);
date_default_timezone_set('Europe/London');
/*
* Setup the include_path to the ZF library.
* We set the incubator first so the
* incubator classes are loaded in preference
* to core ZF classes where two versions exist.
*
* When 0.21 is released, the MVC classes in
* Incubator will move to the core library.
*/
set_include_path(
'./library/incubator/library'
. PATH_SEPARATOR . './library'
. PATH_SEPARATOR . './library/extra'
. PATH_SEPARATOR . './application/tables'
. PATH_SEPARATOR . get_include_path()
);
require_once 'Zend.php';
/*
* Require essential classes
*/
require_once 'Zend/Registry.php';
require_once 'Zend/Controller/Front.php';
require_once 'Zend/Controller/RewriteRouter.php';
require_once 'Zend/View.php';
require_once 'Zend/Session.php';
require_once 'Zend/Config/Ini.php';
require_once 'Quantum/Db.php'; // custom ORM lite solution
require_once 'Quantum/Db/Access.php';
/*
* Create any objects needed for use in
* controllers. Can avoid using a static Registry
* (increases coupling) with this method (cleaner).
*
* Such objects are passed into the Controller
* layer as Invoked Arguments (added to
* Front Controller using setParam()
*/
/*
* Create Registry
*/
$registry = Zend_Registry::getInstance();
/*
* Create View object
*/
$view = new Zend_View();
$view->setScriptPath('./application/views');
/*
* Create Session object
* Expire authentication flag after 5 minutes
*/
$session = new Zend_Session();
$session->setExpirationSeconds(300, 'authenticated');
/*
* Create DB Config object
*/
$db_config = new Zend_Config_Ini('./data/db.ini', 'local');
$registry->set('dbconfig', $db_config);
/*
* Get database connection and set on
* Registry
*/
require_once 'adodblite/adodb.inc.php';
$db = Quantum_Db::factory($db_config);
$dao = Quantum_Db_Access::getInstance($db);
$registry->set('dbaccess', $dao);
/*
* Instantiate a RewriteRouter
*
* Disable default behaviour of allowing
* arbitrary parameters appended to URI
*/
$router = new Zend_Controller_RewriteRouter();
$router->removeRoute('default');
/*
* @todo Set applicable routes (move to new file when large enough)
*/
$routes = array();
$routes['astrum_default'] = new Zend_Controller_Router_Route(':controller/:action', array('controller' => 'index', 'action' => 'index'));
$routes['astrum_login'] = new Zend_Controller_Router_Route('login', array('controller' => 'login', 'action' => 'index'));
$routes['astrum_signup'] = new Zend_Controller_Router_Route('signup', array('controller' => 'signup', 'action' => 'index'));
$router->addRoutes($routes);
/*
* On my platform, I need to set the BaseURL for ZF 0.20
* RewriteBase is assumed to be $_SERVER['PHP_SELF'] after
* removing the trailing "index.php" string.
*
* PHP_SELF can be user manipulated. Avoided using SCRIPT_NAME
* or SCRIPT_FILENAME because they may differ depending on SAPI
* being used.
*/
$base_url = substr($_SERVER['PHP_SELF'], 0, -9);
/*
* Require custom Zend_Controller_Action subclass
*/
require_once('Astrum/Controller/Action.php');
/*
* Setup and run the Front Controller
*
* Set Controller Dir, add the RewriteRouter, set
* params to be passed to Controller, set a custom
* custom Base URL, dispatch the request and get
* the resulting Response object.
*/
$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))
{
require_once 'Zend/Filter/Input.php';
$controller->setParam('post', new Zend_Filter_Input($_POST));
}
if(isset($_GET) and !empty($_GET))
{
require_once 'Zend/Filter/Input.php';
$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('dao', $dao);
$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); will not
* work, it's a bit broken and was fixed in SVN for
* next release. Until then...manually echo exception
*/
if($response->isException())
{
echo $response->getException();
exit(0); // Stop here -
}
/*
* Echo the response (with headers) to client
* Zend_Controller_Response_Http implements
* __toString().
*/
echo $response;
Notably, it's worth avoiding the Zend::register() method since it's an unnecessary static call. You can directly create a Registry Singleton and add it as a Controller parameter (invoked arg) which can be access in your custom Controller class and set to protected properties for use in all Action methods. The same goes for any common use object - the Registry is then limited to storing data/objects between Action methods.
The _forward method specifies that you wish to forward from the current Action to a second Action. Using it you can chain Actions one after the other. This comes in useful when one or more Actions share a common Action dedicated to building a specific View. Once each Action has done it's small part, the end Action (forwarded to) renders a final View. Sorry, no definitive use case yet - but I'm currently using it to forward invalid Controller calls to the IndexController.
A sample Controller based on my setup (the LoginController handles authentication):
Code: Select all
<?php
/**
* LICENSE
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to redux@redux.com so we can send you a copy immediately.
*
* @category Astrum
* @package Astrum_Controller
* @copyright Copyright (c) 2006 Pádraic Brady (http://blog.quantum-star.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/
/**
* Login Controller
*
* @category Astrum
* @package Astrum_Controller
* @copyright Copyright (c) 2006 Pádraic Brady (http://blog.quantum-star.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/
class LoginController extends Astrum_Controller_Action
{
/**
* Forward invalid routes to the IndexController
*
* @access public
*/
public function norouteAction()
{
$this->_forward('index', 'index');
}
/**
* Process the form data and perform authentication.
*
* @access public
* @todo Utilise feyd's SHA256 class for hashing passwords
* @todo Implement challenge/response system
*/
public function indexAction()
{
/*
* Check request type, and redisplay form if not POST
*/
if($this->getRequest()->getMethod() !== 'POST' || !isset($this->_post))
{
$this->_forward('index', 'index');
return;
}
require_once 'User.php';
require_once 'Astrum/Auth/Adapter/Simple.php';
$credentials = new Astrum_User;
$credentials->name = $this->_post->getRaw('astrum_form_login_user');
$credentials->password = sha1($this->_post->getRaw('astrum_form_login_pass'));
$authenticator = new Astrum_Auth_Adapter_Simple;
// if valid token returned, authenticator found user valid and set a "authenticated" session var
// Per bootstrap, authenticated session var expires after 5 minutes since last request
$token = $authenticator->authenticate($credentials, new Astrum_User, $this->_session);
if(!$token->isValid())
{
$this->getResponse()->appendBody(
'<strong>' . $token->getMessage() . '</strong>'
);
$this->_forward('index', 'index');
return;
}
$user = $token->getIdentity();
$this->_view->user = $user->asArray();
$this->getResponse()->appendBody(
$this->_view->render('login_index.tpl.html')
);
}
}
Quick note, the init() function is called by the ctor of the Zend_Controller_Action abstract. No need to override the ctor.
Again, this is based on the current SVN of the ZF, particularly the newer incubator classes.