3
votes

As mentioned in the Zend Framework manual, I created a base controller.

Subclassing the Action Controller

By design, Zend_Controller_Action must be subclassed in order to create an action controller. At the minimum, you will need to define action methods that the controller may call.

Besides creating useful functionality for your web applications, you may also find that you're repeating much of the same setup or utility methods in your various controllers; if so, creating a common base controller class that extends Zend_Controller_Action could solve such redundancy.

But it turns out, that Exceptions are not being called properly from the base... To replicate this, create a file:

/path/to/workspace/library/Joe/Controller.php

Then:

class Joe_Controller extends Zend_Controller_Action
{
    public function init()
    {
        Throw new Zend_Exception('test', 500);
        parent::init();
    }
}

Then in your controller directory, IndexController.php extends off the base:

class IndexController extends Joe_Controller
{

You will find that the exception is uncaught.

If however, you don't extend off the base controller, then throw an exception in init or preDispatch, it will be caught and forwarded to the ErrorController.

Anyone have an idea on getting the exceptions caught from the Base Controller?

Thanks.

UPDATING TO TACKLE THIS ANOTHER WAY

After looking at the various articles and official documentation on how to structure the directories, I went with putting the base controller in library/Joe/...but maybe that's part of the problem...there's no guidance in the manual on how to name and place the base controller. What do the experts with a base controller do?

Another Update

Looking at my code some more, and reading on the net, seems like people suggested in should be:

abstract class Joe_Controller_Action extends Zend_Controller_Action.

Except changing it did not solve the problem...

Now considering that there are articles suggesting to use Base Controllers including the manual, would this be considered a bug in Zend Framework?

To replicate, just throw a Zend_Exception of any kind in the base init or preDispatch. Imagine you poll the database in there, (which is what I'm doing)...and the database is down. No error controller. That's not a good situation unless I'm doing something incorrectly.

My suspicion is that this is a new bug... I don't recall this problem before Zend_Application and I've been using a base controller since ZF 1.5.

3

3 Answers

0
votes

Two thoughts off the top of my head:

  1. Controller names in the default module are usually named like SomethingController. Your name Joe_Controller suggests the module Joe and an empty controller name.

  2. In routing/dispatch, doesn't it look for a matching action before dispatch to the controller? Since the samples have no actions, might you be triggering ControllerNotFound exception?

Just throwin' out some ideas.

0
votes

in Zend philosophy, they provide the init() method to avoid the hassle of

public class Module_TotoController extends Zend_Action_Controller {

    public function __construct(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, array $invokeArgs = array())
        parent::__construct($request, $response, invokeArgs);

        // some init code here
    }
}

just use :

public class Module_TotoController extends Zend_Action_Controller {

    public function init ()
        // some init code here
    }
}

Now, If you look at the Zend_Controller_Action class source, you will notice that the following methods are empty:

  • init()
  • preDispatch ()
  • postDispatch ()

This means, it is useless to call parent:: in your specific controller

public class Module_TotoController extends Zend_Action_Controller {

    public function init ()
        parent::init(); // useless ;-) but you can go for it 

        // some init code here
    }
}

Now, if you want to put an intermediate class between Module_TotoController and Zend_Action_Controller, you expose yourself to a big hassle as:

  • Some controllers won't extend your "base" controller (e.g your ErrorController in your question)
    • so it is not a really a base of your application, is it ?
  • If you put some logic in your init() of that "base",
    • you must call the parent:: in your init(),
    • all the developers in the project need to be aware of that
  • You will ever add another little features to your "Base" controller
    • This will result to a big bloated file
    • Loading/Initializing plenty of stuff you might not really need in that lambda controller
      • Do you need you database on every page ?
        • No: doesn't a $this->_helper->connect(); look nice instead ?
        • Yes: use a controller plugin
  • This "Base" controller won't fit your other projects needs, so that class won't be reusable
    • Action helpers will
    • Controller Plugins will

Hope it makes sense

-1
votes

Don't go for a base or whatever controller

As documentation says :

By design, Zend_Controller_Action must be subclassed in order to create an action controller.

Agreed, this is misleading What they meant is

class Module_TotoController extends Zend_Controller_Action {}

class Module_TotoController extends Joe_Controller is plain wrong (sorry no offence)

as you said your ErrorController can't extend your intermediate Joe_Controller class because your exception will be thrown again in the instantiation of the ErrorController class (as excepted !!!)

The uncaught Exception error is the result of a protection to avoid loops (dig Zend\Controller\Plugin\ErrorHanlder.php line 200-ish)

If you require something to be done for every action, use a Zend_Controller_Plugin and register it with the frontController