I’ve been planning to try out TomB’s MVC implementation for a long time and inspired by the recent “MVC Refactor” thread I’ve decided to give it a go. I’m starting a new thread because I don’t want to engage in the ongoing discussion there at the moment - I think it’s important to be using the pattern in the real world and have some experience to be able to assess it so I’ve decided to try it out in a small project.
For now I want to focus on implementing MVC according to this article (MVC in PHP: Deploying MVC on the web with a Front Controller). At this stage I do not want to get into adding dependency injection containers (yet).
So far I have created the basic framework based on https://r.je/mvc2.phps but the code is not complete enough. I have a front controller, which is very similar:
class FrontController {
private $controller;
private $view;
public function __construct(Router $router, $routeName, $action = null) {
//Fetch a route based on a name, e.g. "search" or "list" or "edit"
$route = $router->getRoute($routeName);
$this->view = $route->getView();
$this->controller = $route->getController();
if ($this->controller) {
//Run the controller action
if ($action) {
$this->controller->{$action}();
}
}
}
public function output() {
//Finally a method for outputting the data from the view
//This allows for some consistent layout generation code such as a page header/footer
$header = '<h1>Hello world example</h1>';
return $header . '<div>' . $this->view->render() . '</div>';
}
}
My problem is with the controller and action part:
- Why are the route name and action split in two parts? The weird thing for me is that the router decides which view and controller to use but not which action. In this example the action comes independently from a different argument - who then decides which action to run and why doesn’t the router decide on that? If the decision about the action comes from an outside entity (like a URL) it may happen that the code will try to run a non-existent action since the front controller doesn’t check for its existence. A more logical approach for me would be to make the router decide which action to run - either from a single URL part (like userEdit, userList, etc.) or from a two-part URL (like User/Edit, User/List, etc.), in which case the router would probably need to validate if an action exists.
- The essential missing part in this example is the arguments that need to be passed to each action. The front controller simply runs the action without any so the issue seems to be ignored here - certainly each action will need a different set of arguments (like request, session, id, etc.) and here the front controller does not know what to pass. Where do I decide about that?
- The $action parameter is optional in the code - but if there is no action then does it make any sense to instantiate the controller at all? The view doesn’t need the controller so to me it is redundant.