MVC Refactor, Take 2

But that’s display logic based on a result. Put the if statement in the template. Chances are, some of the information about a Classic Album and an Album is the same (or we wouldn’t be using the same repository) so we can just use the if to dictate which version to show. The same is true of “Not Found”. This is clearly display logic “If no album is found, display an error” so should go in the view (the template).

By doing this, we can make a generic controller. I’ll use the same album example. The framework could supply a generic controller and interface:

class SingleEntityController {

	public function __construct(EntityModel $model) {
		$this->model = $model;
	} 

	public function get($id) {
		$this->model->load($id);
	}
}


interface EntityModel {
	public function load($id);
}

The developer would then provide the model and template:

class AlbumModel implements EntityModel {

	public function __construct(AlbumRepository $repository) {
		$this->repository = $repository;
	}

	public function load($id) {
		$this->entity = $this->repository->findById($id);
	}

	//For the template to call..
	public function getEntity() {
		return $this->entity;
	}
}

Ok it’s half a dozen of one and six of another, but wait! That can be simplified can’t it, I’d have to write a model for Albums, Blogs, Cars, Products, etc. Consider this:

class RepositoryModel implements EntityModel {

	public function __construct(Repository $repository) {
		$this->repository = $repository;
	}

	public function load($id) {
		$this->entity = $this->repository->findById($id);
	}

	//For the template to call..
	public function getEntity() {
		return $this->entity;
	}
}

Now I can write a route that looks like this:

$model = new RepositoryModel(new AlbumRepository());
$controller = new SingleEntityController($model);
$view = new View('album.html.php', $model);

Or like this:

$model = new RepositoryModel(new BlogRepository());
$controller = new SingleEntityController($model);
$view = new View('blog.html.php', $model);

or

$model = new RepositoryModel(new ProductRepository());
$controller = new SingleEntityController($model);
$view = new View('product.html.php', $model);

In the example you provided, because there are domain concepts in AlbumController (is it an album or a classic album, does it exist or not?) as well as hardcoded template names, this kind of flexibility just isn’t possible and requires a new controller with similar logic for each and every type of domain entity.

edit: The difference between the two approaches is entirely about IoC.