- Understanding MVC: The Basics
- Understanding MVC: Framework Conventions
- Understanding MVC: Coding
[intlink id=”453″ type=”post”]In a previous post[/intlink], I introduce the MVC design pattern, commonly used in frameworks and other programming situations. In that post, I wrote about the Model, View, and Controller parts: their specific roles and how they relate to one another. Those are the fundamental pieces of MVC, but I personally found that knowing what this means in terms of code is a whole different subject. I want to eventually focus on that, but first I have to discuss some of the conventions that frameworks use and how they might differ from one framework to the next.
In this post, I’ll use a hypothetical employees-departments example, giving examples using the Yii framework, the Zend Framework, and Ruby on Rails (these are the three frameworks with which I’m most familiar). If you’re using a different framework, let alone a different language, some of the syntax and particulars will change but the basic principles will still apply, and that’s the important thing I’m trying to get across here. In my next post on this subject, I’ll provide some representative code (I was hoping to do that here, but this subject became too expansive, as commonly happens for me).
Each MVC piece requires a separate file, or in the case of Views, multiple files. With employees and departments, there are MVC pieces for employees and MVC pieces for departments. On the server, the pieces are organized by component type, not subject. In other words, the models folder contains an employees model file and a departments model file; controller contains an employees controller file and a departments controller file; the same goes for a views folder, except that there’s probably multiple View files for each subject. For the Yii framework, model files are named ModelName.php, so Employee.php. A a convention, Yii uses the singular form of a word, with an initial cap; in Zend, it’d be Employees.php, capitalized but plural; in Ruby on Rails, it’d be employee.rb, single but lowercase. In each of these files there would be defined one class, which is the model. The class’s name matches that of the file, minus the extension: Employee in Yii, Employees in Zend, Employee in Ruby (note that Ruby uses lowercase for the file name but capitalized for the class name as most every language capitalizes class names).
Within the Model class, attributes (i.e., variables) and methods (functions) are used to define that class and how it behaves. Depending upon the framework, these members may: indicate relationships to other Models, dictate validation rules, change Model data as needed (e.g., assigning the current timestamp to a column when that Model is updated), and much more.
If the model is based upon a database table, the table is going to have a matching name as well, again possibly manipulated slightly: Employee in Yii, employees in Zend, employees in Rails. Depending upon the framework, the table’s primary key will need to be either id, or tablenameId, or tablename_id. Two things about all these conventions: first, most frameworks allow you to alter the standard behavior, like changing the relationship between the table’s name and the class’s name. Second, it’s best just to go with the conventions the framework sets out. Personally, I like to name my database tables using lowercase and plural, but if I’m using Yii, I’ll just go ahead and capitalize the database table name and make it singular to be consistent to Yii (although database table names may or may not be case-sensitive, depending upon many factors). You could add some code to the Model to indicate non-default behavior, but that’s just extra work and can easily lead to bugs.
For most Models, you’ll also have a corresponding Controller (not always, though: you can have Controllers not associated with Models and Models that don’t have Controllers). For the three frameworks I’ve used most, these files always go in the controllers folder, and have controller in their name: EmployeeController.php in Yii, EmployeeController.php in Zend (singular, even though the Model file is plural), and employees_controller.rb in Rails (lowercase, with underscores separating words). Within each, a Controller class is defined: EmployeeController in Yii, EmployeeController in Zend, EmployeesController in Rails (again, conventionally classes use camelcase).
Within the Controller class, different methods identify possible actions. So with employees, common actions are: create (or new), update, delete, list (all), and show (one). In a Rails Controller class, your methods would be named just so: create, update, delete, show, list. Zend and Yii adds the word action to each method name: actionCreate, actionUpdate, etc., in Zend; createAction, updateAction, etc. in Yii. The method (or function) definition dictates what’s to be done for that particular action.
(As a brief aside here, I’ll talk about how URLs relate to the actions. Most Web frameworks manipulate the URLs so that they’re a bit cleaner and more friendly. Frameworks run through one “bootstrap” file—normally index.php or index.html—that handle the user requests and directs traffic appropriately. Instead of seeing www.example.com/index.php?controller=employee&action=list, the user will see www.example.com/index.php/employee/list [or some variant, like www.example.com/employees/list in Rails]. That requests simply says that the application should go into the employee controller and call the list method. It’s really quite simple and elegant, once you grasp that relationship.)
The final component to cover are the Views, which is the presentation layer. Again, View files go into a views directory. Most frameworks subdivide the views directory by subject: a folder for employees, another for departments. In Yii and Zend, these folder names are singular; in Rails, they are plural (Zend adds another layer in that the views folder contains a scripts folder, which is where the employee and department folders go). There are then different View files for different things one does: show (one item), list (multiple items), create (a new item), update (an existing item). In Yii, these files are named simply create.php, list.php, show.php, and update.php, plus _form.php (the same form used for both creating and updating an item). In Zend, these files are edit.phtml, index.phtml, etc. In Ruby on Rails, which uses embedded Ruby (erb) for Ruby code within HTML files, you’d have: edit.html.erb, index.html.erb, new.html.erb, and show.html.erb.
There’s one more View file involved: the layout. This file (or these files, as one site might have several different layouts) establishes the overall template: beginning the HTML, including the CSS file, creating headers, navigation, and footers, ending the HTML. The contents of the individual View files are placed within the greater context of these layout files. This way, changing one thing, like the navigation, for the entire site requires editing only one file. For comparison, Zend will have layouts/scripts/layout.phtml (note that the layouts folder is in the same directory as the views folder; it’s not within views); Yii has views/layouts/main.php; Rails generates a default layout for each model: views/layouts/departments.html.erb and employees.html.erb. As you’ll learn, you can normally change the layout being used by adding some code to the Controller. For example, on one project I created, the home page used a slightly different layout than every other, so the indexAction method of the SiteController class overrode the layout to use (the index action being the default action and the site Controller being the default controller for the entire application).
Whew! So that’s it for directory structure, file names, and class/method name conventions. It was a bit long and wordy, but before getting into specific code and ideas, I think it’s important to grasp where the code actually goes! I was thinking about also including some screen shots of common layouts, but as there are folders and files I haven’t discussed here, I was worried that could muddy the discussion (let me know if you’d think it’d help). In the next post on MVC, I’ll demonstrate some actual code in each of the MVC components. EDIT: [intlink id=”523″ type=”post”]Here’s the link to part 3![/intlink] EDIT: Here are some screenshots, per a request: