CakePHP

I work as a PHP developer for a small company, the previous developer used cakephp for a couple of sites and I despise having to work on them. I don’t know whether this is down to any combination of: My lack of knowledge of cakephp, the way the previous developer used cakephp or cakephp itself…

However some of the ways things are done (Which seem to stem from the framework, not the previous developer…) seem to be done in really limiting ways.

My main irk is the way it handles models… Setting up the models, defining the relationships I have no problem with, and makes perfect sense… however…

what it calls a “Model” is actually a data mapper of sorts…
For example:

$product = $this->Product->findAll( null, null, 'category_id ASC' )

Is $this->Product a “Model”? I’d argue not… it seems to be a datamapper to me. It isn’t related to a single product in the system, but it’s what CakePhp refers to as a model. Which brings me to my next issue:

The data objects are simple associatve arrays
Once the product has been loaded from the DB it loads it into a simple array… not an object. Which means there’s no way to define a function on a model? Seriously? this is basic functionality for any model isn’t it? I should be able to call $order->getTotal(); which adds subtotal, delivery and the tax for the user’s country? This also has the problem of not being able to use typed parameters (or any kind of type checking) anywhere that data objects are passed around.

Calls to Model->expects()
This is something which I can’t find any proper documentation for but it looks like this:

$this->Product->expects ( array ( 'Image', 'Tag' ) );

What it does it set up the relations which are populated when the product is fetched. These calls are littered throughout controllers. why does the controller have any knowledge of the inner workings of the model?. What this also does, is make the view used by the controller unusable anywhere else unless the models being passed to it are set up the same way elsewhere. Why doesn’t the view require a model, then the model deal with its own relations (Even a simple ActiveRecord approach would be better). I can see why they’re needed… which is to work around the limitations of using arrays as data objects, but this just goes to show why that’s a bad idea in the first place.

I really don’t like the way it does views either, but that’s not nearly as annoying as the way it handles models.

I don’t understand how such a popular MVC framework can get the basics so wrong.

Sorry this is more of a rant than a question and I fully admit it may my understanding that’s wrong and welcome people pointing me in the right direction if that’s the case.

Funny thing is that what you call a model, I would call an entity. In my vocabulary, the model is a layer, which includes a multitude of objects, such as entities, data mappers etc.

I wouldn’t look to CakePHP for any architecture advise or study. The more you learn about software design and application architecture, the more bad things you see in it - everywhere. I believe Cake’s specific database access layer implementation more closely follows an ActiveRecord pattern after Ruby on Rails instead of a DataMapper, though it could be a flawed implementation.

Also, the database access layer should never, ever, ever, ever be named “Model” (and yes, I’ve learned this the hard way myself too). The model layer encompasses so much more than a single class file. It’s the entire data/domain layer for all kinds of data that you work with - databases, sessions, even request objects could be fit into the model layer. Most newer frameworks don’t even define a model anymore - you just use entities and mappers or active records or table data gateways, etc. and other objects that store, persist, and manipulate data for use in your application. These are all understood to be within the model layer.

But the way it’s done (which may very well be wrongly implemented by the developer) the view has no knowledge of the model and only knows of the primitive arrays (which you’re calling entities). Shouldn’t the view access the model directly and request data from the model rather than being passed data from the controller? It just seems a bit backwards and puts all the application logic in the controller. So all the “model” is used for is data access solely by the controller… which is why I don’t think it counts as a proper model.

edit:

Ok… I’m confused over MVC in general and generally finding contradictory information.

this sitepoint article says “It is important to note that in order to correctly apply the MVC architecture, there must be no interaction between models and views: all the logic is handled by controllers.”

Whereas pretty much everything else I’ve read says "Note that the view gets its own data from the model. " which makes far more sense to me… and seems far more widely regarded as “correct” in places which talk about MVC… except where they also mention CakePHP.

So should the controller access the DataMapper directly… then pass it to the view or should there be a model class which contains all the entities used by the controller/view.

For example a simple system where you log in to view your messages


class Controller {
	public function login($username, $password) {
		$model = new Model(); //would be handled via factory in real framework...
		$model->login($username, $password);
		$view = new View($model);
		return $view->output; 
	}	
}


class Model {
	public $user;
	
	public function login($username, $password) {
		$this->user = $this->mapper->user->find(array('username' => $username, 'password' => $password)); //might return null..
	}
	
	public function findMessages() {
		return $this->mapper->message->find(array('userId' => $this->user->id));
	}
}


class View {
	public $output;
	
	public function __construct(Model $model) {
		if ($model->user) {
			$this->output = 'Welcome back ' . $model->user->name . ' these are your messages:<br />';
			foreach ($model->findMessages() as $message) {
				$this->output .= $message->title . '<br />';
			}
		}
		else $this->output = 'You must be logged in to view this page.';
	}	
}


If you removed the model class, it could look something like:


class Controller {
	public function login($username, $password) {
		$user = $this->mapper->user->find(array('username' => $username, 'password' => $password)); //might return null..
		$view = new View($user);
		return $view->output; 
	}
}

class View {
	public $output;
	
	public function __construct(User $user) {
		if ($user) {
			$this->output = 'Welcome back ' . $user->name . ' these are your messages:<br />';
			foreach ($user->messages as $message) {
				$this->output .= $message->title . '<br />';
			}
		}
		else $this->output = 'You must be logged in to view this page.';
	}	
}

Hasn’t the “model” become both the User object and the $mapper->User. Obviously now $user needs some way of accessing the messages but that’s a different issue. The model is still there but somewhat split up between different classes… without a root model class.

Is this what you mean by “Most newer frameworks don’t even define a model anymore”.

Surely by splitting it all up it’s harder to test? With a distinct model testing should be far easier shouldn’t it?

Yes, there’s much confusion. The confusion happens on two levels; There’s the problem that people don’t agree on what certain words means. Model can mean different things for different people. And then there’s the problem that people disagree on which architecture works better, even if they speak a common language. In combination, communication often breaks down.

Model is nowadays often used as meaning an object that represents some kind of data-type in the application. For example a User or an Account. This concept maps more or less to a single row in a database table or view. This use of the word means that you can speak of models in plural.

Another - more correct - use of the word model is that you consider your application as consisting of a collection of classes that represents a mental model of the domain that it deals with. This is distinct from the part of the application that has to do with presenting the model. In this use of the word, Model is always singular: You application has one model. The model is not represented by a single concrete class, but rather by a subset of the applications code, usually consisting of many classes.

The second use of the word is older than the first one, and most literature will use the word like this.

There is a similar confusion about the concepts of controller and view. Some people will use view as synonymous for template, while others won’t. This has implications for which tasks each component should take care of. Without having read the above article, I would assume that the author is using view as meaning template, and thus operates with a presentation-layer that combines controller and view tasks into one component (Which he then calls a controller). An alternative is to separate the two, in which case the controller should certainly not act as middleman between model and view. But it’s really hard to speak about, because people don’t agree on what these concepts really mean.