Implementing ToMVC

You’re right, of course :slight_smile: For the purposes of a simple demonstration script I didn’t really want to get into the topic of breaking apart the URL so wanted to rely entirely on $_GET parameters. as you suggest, in a real-world project it would be better to generate $aciton and $controller by splitting the request uri and providing some sensible defaults if it doesn’t match up.

There’s actually some better examples of this in the other thread.

This is basically the same as 1) it’s a simple example to demonstrate the concept rather than a complete solution.

This is certainly a possibility and one I’m on the fence on. On the one hand there are 3 different processes:

  1. Decide which controller/view/model/action to use
  2. Call the action
  3. Do something with the response

While 1 and 2 can probably be merged (if one changes, the other does so it follows that they’re a single responsibility), the third one may not.

In the real world I have the Front Controller construct two MVC triads:

  1. Based on the action requested by the URL as the examples show
  2. A MVC triad for the layout. The model has a variable $content, which is set by the front controller and contains the HTML output from the other triad. The template for this triad contains all the HTML for the layout, <head> tags, <title> tags, etc.

As an aside, each view has a $css (array), $js (array) and $title (string) property which is readable by its parent view. This way the layout can be generated and include any css/js files that are required.

Firstly, it’s worth considering the difference between the variables. $_POST, $_GET and $_SERVER are variables that are populated externally whereas $_SESSION is controlled entirely by the PHP script, think of it as encapsulation: The data in $_SESSION can be considered safe, whereas the others cannot. As such, they need to be treated differently. A request object should contain only those things that come from the request $_POST, $_GET and $_SERVER and $_COOKIE and be considered read-only. Setting a cookie is part of the application logic (Store some information) and belongs in a model (probably abstracted to its own class!)


<?php
$request = new Request();
$route = new Route($request);
$frontController = new FrontController($route);
$frontController->output();

Personally I prefer to do routing based on $_SERVER only as it keeps things simpler and then keep $_GET and $_POST for data. That way the router has a dependency only on $_SERVER:

$router = new Router();
$route = $router->getRoute($_SERVER);
echo $route->getView()->render();

By constructing the MVC triad using a DIC, the controller/model can ask for the Request object (containing $_GET and $_POST) in its constructor if it requires it and the router is unaware.

The router then constructs the controller like this:

//Would really need some better routing than this, but for simplicity:
list($model, $controller, $action, $arg1, $arg2) = explode('/', $server['REQUEST_URI']);
$controller = $dic->create($controller);
$controller->{$action}($arg1, $arg2);

Then the router doesn’t care about the Request object, the controller can look like this;


class Controller {
	public function __construct(Request $request) {
		$this->request = $request;
	}
}

or like this:

class Controller {
	public function __construct(SomethingElse $somethingElse) {
		$this->somethingElse = $somethingElse;
	}
}

And the router doesn’t need to know about it. The biggest advantage of this is that the controller’s constructor arguments can change and the router doesn’t need to be reconfigured. Hopefully that’s some food for thought! Doing this without a DIC is a lot more difficult because it means you need to put DIC logic in the router (What dependencies does each class have?)