2

I've read a lot of MVC articles, for example like this site and this. I still not understand why is controller should be passed to view class?

<?php
$model = new Model();
$controller = new Controller($model);
$view = new View($controller, $model);

if (isset($_GET['action']) && !empty($_GET['action'])) {
    $controller->{$_GET['action']}();
}

echo $view->output();

when we can call controller action in bootstrap or front controller and then what is purpose of this?

$view = new View($controller, $model);
Pattisahusiwa
  • 205
  • 2
  • 8
  • The first link, the author exposes: "N.b. the controller is passed to the view because in a desktop application, the view would need to create a callback on the correct controller, so it would need to know which controller was in use. This still happens on the web, but it a more subtle way. In Part 2 I'll show how this is worked around on the web.", though I do not agree. – Tomás Feb 17 '14 at 17:07
  • thank for your quick response. it's mean, when I just have 1 method in controller (just action), so I don't need to pass the controller to view class? – Pattisahusiwa Feb 17 '14 at 17:12
  • 2
    The author of that article is making mistake by passing controller to the view. Controller in MVC pattern is responsible for altering state of model layer and view. View is not responsible for altering controller. I get a feeling that author wanted to apply classical MVC pattern, without actually understanding how communication between view and controller is handled. – tereško Feb 18 '14 at 16:40

1 Answers1

2

Theory

In a macro design level the MVC is a architectural decision that states that there are three concepts in development that must be separated. Model, View and Controller.

To avoid more "MVC theory" duplication over SO, this is a very accepted answer where it is explained the basics of MVC: https://stackoverflow.com/a/5864000/1311025

Implementations of MVC

You have to choose the implementation that is right for your project requirements and perspectives of changes.

For example. If I develop thinking that my database will change in the future (I don't know when, I just suspect it will change) I'll make an implementation that decouples absolutely my database, creating a layer that abstracts the implementation of it from the controller. and implement a factory that provides you the right instance to access the database.

If I think my view will change, then I'll use an observer pattern in the view to decouple both controller and view. And with events the controller and the view will communicate.

You can then, construct your own implementation of MVC following software design patterns that fulfill your needs.


Now, from the code you provided,

<?php
$model = new Model();
$controller = new Controller($model);
$view = new View($controller, $model);

if (isset($_GET['action']) && !empty($_GET['action'])) {
    $controller->{$_GET['action']}();
}

echo $view->output();

thought is separating the responsibilities in classes (Model, View and Controller), for me, this is an example of coupling the view with the model. But It could be right if we want that the view, the controller and the model will be forever like this and will never change.
Also with this implementation the controller has an state, which reflects that this will never scales (or not in an easy way).

Disclaimer: This is my implementation for an easy, quick and little project. If you need a more serious solution, where quality is not an option, then you must follow more strict guidelines.

In my opinion, I'll choose to decouple at least the view from the model.

<?php
$controller = new Controller();
if (isset($_GET['action']) && !empty($_GET['action'])) {
    $controller->doAction($_GET['action']);
}

The controller does not have to handle with global php variables ($_GET):

<?php
Controller {
     public function __construct() {}

     public function doAction($action) {
        $model = new User();
        $model->setName("user36279");

        //This just transforms the user model in an associative array
        $UserDTO = $model->toDTO();
        $view = new UserView();
        //We don't send the model to the view increasing decoupling  
        $view->render($UserDTO);
     } 
}

But this would be my implementation. Now is your choice to decide how much you want to decouple, how much maintainability, complexity, testability you want.

Edit:
Someone pointed that:

[...] your "controller" is actually responsible for routing, retrieval of information from model layer and rendering of response, which of course is violating both SRP and SoC. Bottom line: all of this is completely wrong

He is right, my code is violating SRP. But check out this question:
Does the traditional use of the controller in MVC lead to a violation of the Single Responsibility Principle?

And if you want to follow the SRP, you disaggregate your Controller into a Dispatcher and Actions; the Dispatcher dispatches control to its actions [...]

Why don't we see this more often? Because Controllers are often "ad hoc" implementations, leaf-level concrete classes that aren't generalized and aren't meant to be subclassed. Here, the class is used more to conveniently group code, the actions are almost certainly non-public (likely private, maybe protected), "merely" internal implementation details.

The choice of how to decide what action to dispatch to, the number and diversity of possible actions, is high, and dispatching and action are tightly-coupled. So in practice, it's often easier to just put the code together in one place.

SOLID principles are a great guideline to design object oriented. The general rule here is to acknowledge the different alternatives and choose the one that best fit your needs. Principles are guidelines not rules and the major advantage of following the principles are a set of common solutions that are agnostic of languages, easy to use and understand for both novices and expert developers and simplicity in our design.

Bottom line: It's up to you when you need to apply SRP (Single Responsibility Principle) and consequently, SOLID.

Community
  • 1
  • 1
Tomás
  • 3,501
  • 3
  • 21
  • 38
  • 2
    -1 "Domain model" is a concept to describe accumulated knowledge for a given project. **It has nothing to do with MVC.** Model is not an object nor a file. Basically, You are completely wrong. And your "controller" is actually responsible for routing, retrieval of information from model layer and rendering of response, which of course is violating both SRP and SoC. Bottom line: all of this is **completely wrong**. – tereško Feb 18 '14 at 16:45
  • 3
    Tomas, allow me to balance out the above contributor by thanking you for such an extensive effort. If only every answer was as thorough! There are a few tags that attract quite strongly held views, and as you'll discover, [tag:mvc] is one of them. – halfer Feb 19 '14 at 00:23
  • Tomas, allow me to balance out the above contribution by saying it is exactly as teresko said. Do not confuse people more then it already is. Also your code has other code smells such as the use of new in this case which kinda contradicts `The controller will be stateless, and completely reusable and testeable` the code you presented is not... – Ronni Skansing Feb 19 '14 at 01:04
  • Thank you for pointing out the errors. To avoid duplication I provided a link to tereško answer about MVC (Which is far more complete). For the rest of the answer, I'll put a bigger warning that this is my pragmatic implementation for a quick and little project. Implementations always differ from what OP really needs and from what purists really want to see. – Tomás Feb 19 '14 at 11:12