Hey folks,

in my current project i built up a widget system based on ZF which allowes
to run a front controller twice or more during runtime and getting the
response of a so called subrequest in a view with:

<div id="calendar">
  <?php echo $this->widget("calendar", "utils", "global-module"); ?>
</div>

This post is for those who are interested in chaining the front controller
object and getting allways the right instance when calling
Zend_Controller_Front::getInstance().

The Problem with current Zend_Controller_Front is, that it implements the
singelton pattern and it allways give the current instance back. that means,
its not possible to have more than one instance at the same time. of course,
this behavior is neccessary for the helperbrooker, but this is another
topic.

i came up with the following code, use it as you wish and i am pleased if
you have any notes or comments:

class RF_Controller_Front extends Zend_Controller_Front
{

        static protected $_instance_chain = array();

        protected $_instance_parent;

        /**
         * This function creates a new instance of the RF_Controller_Front 
class.
         * 
         * @author Markus Siebeneicher <[EMAIL PROTECTED]>
         * 
         * @param Zend_Controller_Front $parentFrontController
         * @return RF_Controller_Front
         */
        static public function initFrontController(Zend_Controller_Front
$parentFrontController = null)
        {
                // Der Broker instanziert einmal einen helper und nimmt ihn für 
jeden
neuen controller.
                // Leider auch bei neuen FrontController Instanzen, drum 
instanzieren wir
die notwendigen
                // Helper neu.
                // XXXMSi: ersetzt das den vorherigen helper global, also auch 
im
controlle und ist nicht mehr
                // verfügbar?
                Zend_Controller_Action_HelperBroker::addHelper(new
RF_Controller_Action_Helper_ViewRenderer());
                Zend_Controller_Action_HelperBroker::addHelper(new
RF_Controller_Action_Helper_Layout());
        
                // Register Controller Action Helper
        
Zend_Controller_Action_HelperBroker::addPath('./libraries/RF/Controller/Action/Helper',
'RF_Controller_Action_Helper');

                // create new instance of RF_Controller_Front
                $frontController = RF_Controller_Front::createInstance();
                
                // adds controller directories to the front controller
                
$frontController->addControllerDirectories(RF_Module::getModules());

                // Shall an error be printed out?
        
$frontController->throwExceptions(Zend_Registry::getInstance()->rfConf->error->throwEception);

                
$frontController->setDefaultModule(RF_APPLICATION_DEFAULT_MODULE)
                         
->setDefaultControllerName(RF_APPLICATION_DEFAULT_CONTROLLER)
                         ->setDefaultAction(RF_APPLICATION_DEFAULT_ACTION)
                         ->setRouter(new Zend_Controller_Router_Rewrite())
                         ->registerPlugin(self::_initPluginErrorHandler())
                         ->registerPlugin(new RF_Controller_Plugin_Acl())
                         ->registerPlugin(new RF_Controller_Plugin_Init())
                         ->registerPlugin(new RF_Controller_Plugin_Locale())
                         ->registerPlugin(new RF_Controller_Plugin_Layout());
                         //->registerPlugin(new RF_Controller_Plugin_Logger())
                         //->registerPlugin(new 
RF_Controller_Plugin_Frontend());

                if($parentFrontController instanceof Zend_Controller_Front) {
                        
$frontController->setInstanceParent($parentFrontController);
                }
                         
                return $frontController;
        }

    /**
     * Singleton instance
     *
     * @author Markus Siebeneicher <[EMAIL PROTECTED]>
     * 
     * @return RF_Controller_Front
     */
    public static function getInstance()
    {
        if (null === self::$_instance) {
            self::$_instance = new self();
            self::$_instance_chain[] = self::$_instance;
        }
        return self::$_instance;
    }
    /**
         * Creates new instance and moves previous back in the chain.
         * 
         * @author Markus Siebeneicher <[EMAIL PROTECTED]>
         * 
         * @return RF_Controller_Front
         */
        public static function createInstance()
        {
                self::$_instance = null;
                return self::getInstance();
        }
        /**
         * Destroys last RF_Controller_Front instance.
         * 
         * @author Markus Siebeneicher <[EMAIL PROTECTED]>
         * 
         * @return void
         */
        public static function destroyLastInstance()
        {
                if(self::$_instance_chain[count(self::$_instance_chain) - 1] !==
self::$_instance) {
                        throw new Exception("Last entry of \$_instance_chain is 
not equal with
\$_instance, in ". __METHOD__);
                }

                if(is_array(self::$_instance_chain) && 
count(self::$_instance_chain) > 0)
{
                        array_pop(self::$_instance_chain);
                        if(count(self::$_instance_chain) > 0) {
                                self::$_instance = 
self::$_instance_chain[count(self::$_instance_chain)
- 1];
                        }
                }
        }
    /**
     * Resets all object properties of the singleton instance
     *
     * Primarily used for testing; could be used to chain front controllers.
     *
     * @author Markus Siebeneicher <[EMAIL PROTECTED]>
     * 
     * @return void
     */
    public function resetInstance()
    {
        $reflection = new ReflectionObject($this);
        foreach ($reflection->getProperties() as $property) {
            $name = $property->getName();
            switch ($name) {
                case '_instance':
                    break;
                case '_instance_chain':              // <-
                    break;
                case '_controllerDir':
                case '_invokeParams':
                    $this->{$name} = array();
                    break;
                case '_plugins':
                    $this->{$name} = new Zend_Controller_Plugin_Broker();
                    break;
                case '_throwExceptions':
                case '_returnResponse':
                    $this->{$name} = false;
                    break;
                case '_moduleControllerDirectoryName':
                    $this->{$name} = 'controllers';
                    break;
                default:
                    $this->{$name} = null;
                    break;
            }
        }

        if (!Zend_Controller_Action_HelperBroker::hasHelper('viewRenderer'))
{
            Zend_Controller_Action_HelperBroker::addHelper(new
Zend_Controller_Action_Helper_ViewRenderer());
        }
    }
    

        static private function _initPluginErrorHandler()
        {
                $errorPlugin = new Zend_Controller_Plugin_ErrorHandler();
                $errorPlugin->setErrorHandlerModule('rf-frontpage')
                                ->setErrorHandlerController('error')
                                ->setErrorHandlerAction('error');
                return $errorPlugin;
        }

        /**
         * Sets the parent front controller object.
         * 
         * @author Markus Siebeneicher <[EMAIL PROTECTED]>
         * 
         * @param Zend_Controller_Front
         */
        public function setInstanceParent(Zend_Controller_Front $front)
        {
                $this->_instance_parent = $front;
        }
        /**
         * Get the parent front controller object.
         * 
         * @author Markus Siebeneicher <[EMAIL PROTECTED]>
         * 
         * @param Zend_Controller_Front
         */
        public function getInstanceParent()
        {
                return $this->_instance_parent;
        }

}
-- 
View this message in context: 
http://www.nabble.com/chaining-the-front-controller-tf4625668s16154.html#a13209321
Sent from the Zend Framework mailing list archive at Nabble.com.

Reply via email to