ZF-4385: Create Zend_Controller_Action_Interface and make Standard Dispatcher check for it.


Currently the whole controller dispatcher and controller action components are very thighly coupled, since the Standard Dispatcher checks for an Zend_Controller_Action instance before dispatching. I propose to include a Zend_Controller_Action_Interface with just the constructor and the dispatch method required for any implementation. Make Zend_Controller_Action implement the new interface and the Standard Dispatcher to accept the interface as allowed action controller.

Advantages: * Standard Dispatcher (Dispatcher in general) and Action Controller are now lously coupled. * People can implement their own action controller following their needs. * No BC issues, only added a new interface, old functionality stays 100%. All Unit-Tests still succeed. * Even when MVC will be refactored in the future, this is still just a simple change that may lead only to problems for those who changed from the default Zend_Controller_Action implementation to a user-implemented one and those have probably to refactor anyways.

My use case would be to implement a new controller that handles everything as a SOAP request, you could of course insert any other webservice, so that a controller MyApp_Controller_Action_Soap will completly handle soap requests and still have all the advantages of a front controller approach. Currently you have to write non-DRY code for this or overwrite the Zend_Controller_Action class and have the problemt that many methods in the abstract class are public and even final, and can't be restricted access to.


Patch implementing a new Zend_Controller_Action_Interface, having the action controller implement it and changing the Standard Dispatcher to accept the interface as correct action controller implementation.

ah its probably important to say, the patch has to be applied to library/Zend/Controller directory. :-/ my mistake

I just voted for this issue. I was actually quite amazed that a basic thing like this has been so thightly coupled for such a long time. I didn't expect to find that in framework that tries to have / has a use-at-will architecture ;)

Resolved in revision 14138

Jurrien -- we actually need to back this out as it introduces a BC break.

... and should have noted that it's a good candidate for 2.0...

Curious... how does this break BC? Unit tests still pass...

Because it changes the types it looks for. I'll take a closer look, however. Let's discuss on Monday.

I'm currently behind a firewall that doesn't allow me to do anything, including committing changes to SVN. Will be able to do that later today. However, if the type check is the main concern, this simple check in Zend_Controller_Dispatcher_Standard would resolve that:

Line 262:

if (!($controller instanceof Zend_Controller_Action_Interface) ||
    !($controller instanceof Zend_Controller_Action)) {

I've applied the patch I proposed in my previous comment in revision 14152. This resolves any BC issues that might have occurred with the first patch.

I ran into a problem with this interface as implemented in 1.8.4, in that my test harness defines classes for each controller under test, as described in this article:


to the point, I am extending a controller and changing the constructor (and its signature) in the derived class. This is not possible with the new Zend_Controller_Action_Interface.

I know supporting this method is not the concern of ZF, but the new interface does break this approach. The larger problem is that it breaks general OOP design principles, in that derived classes should be free to instantiate themselves however they see fit. WIth the new interface, ANY class implementing Zend_Controller_Action_Interface -- INCLUDING any class that extends Zend_Controller_Action -- must have that constructor signature. This just seems wrong. In fact, I found much supporting arguments for all sorts of OO languages when doing a quick google search on this subject: http://google.com/search/?q=interface+constructor

This is my first ZF comment, so I apologize for not having a lot of the history here. But I hope this causes some second thoughts about placing constructors in the interface, thereby enforcing needless constraints on any derived classes.

Could you open a separate issue for that please? :)