About the MVC pattern in major PHP frameworks and Sitepoint's forum stickied thread

Well I’ve been trying to implement my own MVC framework for a while now. I’ve been following a structure quite similar to PHP major frameworks such as Zend, Symfony, CakePHP, Codeigniter and Yii, which uses a front controller that delegates its actions to those app controllers. However, after I viewed this thread on sitepoint, I am a bit confused:

As you can see, the design seems quite different. In major frameworks, each action is defined as methods inside an app controller such as public function edit() or public function editAction(), while in the thread from sitepoint, each action is a command class like Class UserAddCommand and Class UserEditCommand. For this, I have a few questions to ask:

  1. Is it a better approach to define each action as a command class/object(sitepoint’s example), or as a method inside a controller(like php major frameworks)? Sitepoint’s example is more similar to the way Martin Fowler originally illustrated the controller pattern, but why isnt it widely adopted in php frameworks?

  2. What is the difference between an app controller in CakePHP/Codeigniter and an application controller as defined by Martin Fowler? Are they the same thing? They seem to be doing different tasks, though both are referred to as app controllers…

  3. Sitepoint’s MVC example also has each view defined as view classes(such as Class UserAddView and Class UserEditView), in which the html code is generated from PHP script. Is it a better practice than to embed PHP in html as what major frameworks are doing?

This is a big topic without a straightforward answer. I’ve written about the differences here: http://r.je/views-are-not-templates.html and there was a very good discussion about the differences here: http://www.sitepoint.com/forums/showthread.php?1008353-MVC-vs-PAC that was split off from a similar discussion. There’s a post here: http://stackoverflow.com/questions/7621832/architecture-more-suitable-for-web-apps-than-mvc/7622038#7622038 which details some of the variations (Although I’m not sure I agree 100% with the accuracy, it’s a good starting point)

What it boils down to is that, in MVC (as described by Fowler, other academics and pretty much everyone else outside the PHP world) a controller is tied to a single view, it doesn’t do view selection and it handles actions that apply to that view only. E.g. a list of blogs could have sort, search, delete and edit actions. Sort, delete and search all result in the same view (a refresh of the list) whereas editing a record requires a different view, and therefore a different controller.

What the PHP community did (branching from Ruby on Rails who seem to be the starting point of this) was take a PAC architecture and call it MVC because they were trying to implement MVC, however, web MVC stemmed from joining an entry point, a template and a database abstraction layer, components which existed years before the term MVC was being thrown around, people started labelling what they were already doing as “MVC” because they didn’t understand what MVC is. And here we are, over a decade later and this simple mislabelling has created all sorts of confusion and problems within the PHP community.

I can’t think of any practical benefit to the one-action-per-class approach. On the other hand, if you have related actions within the same class, like the major frameworks do, then you can use private methods to consolidate any repetitious code between actions.

Sitepoint’s example is more similar to the way Martin Fowler originally illustrated the controller pattern, but why isnt it widely adopted in php frameworks? … What is the difference between an app controller in CakePHP/Codeigniter and an application controller as defined by Martin Fowler? Are they the same thing? They seem to be doing different tasks, though both are referred to as app controllers.

As TomB and his links noted, the architecture that Fowler called MVC and the architecture that frameworks now call MVC are actually quite different, and trying to figure out how the two match up can be a bit like trying to figure out how the round peg fits into the square hole.

Sitepoint’s MVC example also has each view defined as view classes(such as Class UserAddView and Class UserEditView), in which the html code is generated from PHP script. Is it a better practice than to embed PHP in html as what major frameworks are doing?

Those example views also echo just a single line of text. If they started trying to generate whole pages of HTML, then I think it would become more obvious that it’s better to embed PHP in html, like the major frameworks are doing.

Fabien Potencier, the creator of Symfony, has a “Create Your Own Framework” book (of sorts) that you may find interesting.

It’s not one-action-per-class! It’s one-controller-per-view! The reason for this is that it allows you to remove the repeated view generation logic from each controller action. Why does every action need to call $this->render() or similar? It’s redundant!

I went back and re-read the OP’s post, and he was definitely asking about one action per class. Quote:

In major frameworks, each action is defined as methods inside an app controller such as public function edit() or public function editAction(), while in the thread from sitepoint, each action is a command class like Class UserAddCommand and Class UserEditCommand. For this, I have a few questions to ask: … Is it a better approach to define each action as a command class/object(sitepoint’s example), or as a method inside a controller(like php major frameworks)?

I see, so those frameworks aint actually using MVC at all, or we can say they are using PAC that is labeled as MVC? Come to think about it, I do remember Java’s MVC being quite different. The variations among controllers are so obvious, although I am still a bit confused when it comes down to the concept of appcontroller/applciation controller. Isnt PHP frameworks appcontroller more like page controllers rather than application controllers? The view is actually a GUI container that handles not only the construction of GUI components, but also a listener for user mouse/keyboard events. Those things are all nonexistent in server-side programming, although its possible to mimic them by turning HTML elements into GUI components/containers.

And yeah, I am still curious at whether it is more appropriate in a PHP application to define each controller action as a method in those so-called appcontrollers, or as command class/object.

More or less, yes. For example, Symfony defines a controller as any callable that accepts a request and returns a response.

I don’t think either option is any more appropriate than the other, but keeping related actions as methods within a class comes with practical benefits.

I see, this makes sense to me. Wonder why CakePHP and Codeigniter name them appcontrollers rather than page controllers, perhaps thats just the way PHP frameworks work, their MVC is not the original definition of smalltalk MVC anyway.

I don’t think either option is any more appropriate than the other, but keeping related actions as methods within a class comes with practical benefits.

Thats true, it is the approach I’ve been following for a while. I was wondering though, what would you do when your controller action method gets too big? Does this imply that an implementation of fat controller design, which is bad since the better way should be fat-model-thin-controller?

Also there is a small issue that at least 80% action method will check this if…else condition:


if($this->form->isSubmitted(){
    // business logic for execute form. 
}
else{
    // business logic for display form.
}

Tbh I have no idea how to avoid this code duplication, although it may not be that bad considering even many large PHP frameworks are doing the same thing.

Hmm, one reason I can think why it’s not redundant is that in the internet world not every action renders the page in the browser. An action can launch a file download operation, send data in a specified format like xml, json, etc. or it can simply do some internal database work like storing information from POST and ending up issuing an http redirect header.

Unless I am missing something, isn’t it the job of the specific action to decide what kind of response to send back to the browser? Yes, in most cases it will run render(), but it can also run download(), sendXml(), redirect(), sendHttpErrorCode(403), etc.

Usually that means you can, and possibly should, refactor some of that logic out of the controller and into reusable classes. For example, the logic to define and validate a form can be implemented in separate classes. Or the logic that alters your application’s data can be implemented in model classes.

I suspect other frameworks allow this as well, but in Symfony, we can define our routes by not just the URL, but also the request method. So GET /path/to/edit could send you to the edit action, where the form is merely displayed, and POST /path/to/edit could send you to the update action, where the form is processed.

No, what kind of response goes back to the browser is clearly the job of the view. Whether the view is displaying a PDF, a CSV or a HTML page isn’t a concern of the controller. A controller is concerned with handling user input, that’s all. It shouldn’t matter what the view is doing, the view could be outputting the data as a pie chart in a jpeg, but it’s no concern of the controller’s. This is the exact reason why tightly coupling views and controllers in the way that most of the big frameworks do is a very bad idea. In MVC you’d simply substitute the view, keeping the same model and controller. The view could be formatting the data in any way. Using a controller to decide which view to show introduces repeated logic as soon as you want to do this.

I see, thats indeed a good way to demonstrate the idea of fat-model-thin-controller.

I suspect other frameworks allow this as well, but in Symfony, we can define our routes by not just the URL, but also the request method. So GET /path/to/edit could send you to the edit action, where the form is merely displayed, and POST /path/to/edit could send you to the update action, where the form is processed.

Well if each action/command is defined as class rather than controller method, you will be able to execute the control logic or switch statement in the front controller class to decide which method for the command class to run. The command class may consist of two separate methods for standard action and form-post action. But yeah, there are indeed practical issues with having action/command as separate classes, so I am not sure if the benefit of avoiding code duplication like form submission check will actually make good compensation for its issues.

Yes, this makes sense after you’ve explained it. But where would redirection go in this case? It seems weird to have a view whose only job is to send a redirect header. Redirection is usually done after collecting POST data - the controller passes the data to appropriate classes that save it to the database (or log the user in, etc.) and then who is responsible for redirecting the user to the next page?

It’s debatable but this is technically program flow rather than display logic. Yes “Display a thank you message” is display logic, but “this view is no longer relevant” is not. It’s actually an exit(). In a desktop application, this would be analogous to closing a window; neither the view or the controller that were active are now relevant. Where you’d go back to would be another window… another view with its own controller.

Yes, you could have “redirect” as a view but it doesn’t really fit into the MVC concept as the redirect will always happen as the result of user input rather than as a direct result of any display logic. You could even argue “Which view is active” is application state, which nudges the idea towards a top level model which handled the state of the overall application! (However, this doesn’t make sense in PHP!)