I once read somewhere that, as a general rule of thumb, the correct way to use an MVC framework is to make sure the models and views are at least as big as the controllers. This is very good advice.
I don't know about anyone else, but when I started out writing projects in CakePHP, I wasn't sure where to put a lot of code and, when in doubt, I put it all in the controllers. After a while, I realised there was a much better way of working: putting pretty much all the code that deals with the database in the models, and pretty much all the code that deals with the user interface in the views, leaving the controllers with just the overall logic of the page to deal with.
Let's look at a concrete example. I worked on a project where people bought products and subscribed to magazines. When I was making the product buying section of the website, I needed to find out if the person who was logged in had to pay VAT or not, which could be worked out by looking up their ID in the users table, pulling out a few bits of data and comparing them. The wrong way of doing this, tempting because of its familiarity to programmers used to procedural programming, would be to write a few lines of code in the Products controller that does the necessary work.
A much better way is to create a method in the User model that accepts a user's ID as its input, returns whether they need to pay VAT or not as its output, and does absolutely nothing else. Then in the Products controller, you should simply call the User model's new method in a single line of code to work out whether the customer should pay VAT or not.
Because this was my fourth project with CakePHP, I'd already gotten to the point where I knew this was a better way of doing it. My point, though, is why it's a better way of doing it: a few days later, I was working on the Subscriptions controller, and sure enough, I needed to yet again work out whether the customer had to pay VAT or not. This time, I didn't have to copy and paste twenty lines of code. I just had to write the one line that called the new method in the User model. This saved me not only the time of writing all that code out again, but also the time of testing it again, and the hassle of having to maintain the same piece of code in multiple places.
Although it's sometimes tricky to work out whether you should be putting code in a model, view or controller, try to bear these tips in mind:
- The controller should usually be no bigger than its views and model
- The model, not the controller, should have any code that talks to the database
- The view, not the controller, should have any code that talks to the user
- If you're about to copy and paste more than one or two lines of code, see if that code should instead be moved to somewhere that can be called from both locations
Of course, these are just general rules and sometimes it's better to break them. Generally, though, you'll be better off with slim controllers.