Special Episode : How the magic is done
(requested by james)
It is some times quite confusing to use Joomla MVC, as we are quite often not sure where are the related files are included and how the respective controller/ model/ view are found and invoked. This post is trying to answer that question.
0. Naming Convention
The naming convention is some how annoying in Joomla MVC. The class name is quite consistent which is always:
[COMPONENT_NAME][CLASS_TYPE][ITEM_NAME]
For example:
- SchoolControllerStudent, is a JController instance dealing with Student operations of School component (com_school).
- SchoolModelTeacher is Teacher model of School component.
- SchoolViewAttendance is Attenance view of School component.
so far so good, why is it annoying? when the file name comes in, see the below table:
| Class Name | sits in folder | File name |
| SchoolController | / | controller.php |
| SchoolControllerStudent | /controllers | student.php |
| SchoolModelTeacher | /models | teacher.php |
| SchoolViewAttendance | /views/attendance | view.php |
For controller, there are 2 cases, the default controller, which will sit in the “/” folder location and always named controller.php, and when there are more than one controller, they’ll be put in “/controllers/” and named based on its purpose. Actually, its filename will match a “controller” parameter in the request. See the standard code piece below in the entry point file:
// Require specific controller if requested
if($controller = JRequest::getWord(’controller’)) {
$path = JPATH_COMPONENT.DS.’controllers’.DS.$controller.’.php’;
if (file_exists($path)) {
require_once $path;
} else {
$controller = ”;
}
}
For the Models, it is very simple, just follow the item name and place them in “/models"/” folder will do the job.
For the Views, it is again becoming irritating, the php file is always called “view.php”, instead, the subfolder name need to match the class name this case: “/views/[VIEWNAME]/view.php”. Add to the complexion, the is always a “tmpl” template folder, inside there “default.php” is for the default layout, all other files corresponds to the layouts same to their filenames.
—— The blog entry starts here officially ——
There are many magical methods in the Joomla MVC API, they automatically find the correct php file (as long as you’ve put them in the correct folder) and initiate a instance when needed. Let’s see a list of them:
- *.getName()
- JModel.getInstance($type, $prefix = ”, $config = array())
- JModel.getTable($name=”, $prefix=’Table’, $options = array())
use $this->getName() if $name is empty; - JView.get($property, $default = null)
- JView.getModel($name = null)
- JController.getModel($name = ”, $prefix = ”, $config = array());
- JController.getView($name = ”, $type = ”, $prefix = ”, $config = array())
JModel is initiated in JController and passed to JView.setModel in JController.display
1.*.getName()
They all share a very similar getName() method, which basically return the “name” of the model / view / controller.
First of all, let’s take a look at the regular expression they used in the three classes for .getName() method
| Type | Regular Expression | Match Group |
Eg | Result |
| JModel | /Model(.*)/i | 1 | SchoolModelStudent | Student |
| JView | /View((view)*(.*(view)?.*))$/i | 3 | SchoolViewTeachers | Teachers |
| JController | /(.*)Controller/i | 1 | SchoolController SchoolControllerStudent |
School School |
As we mention before, as the controller will be picked at the component entry point (part 0), there is no way that 2 controller having the same “name” being run at the same time.
2. JModel.getInstance()
This is the actual place where every JModel is being initiated, it search for a file named “$type”.php in the included paths:
$modelClass = $prefix.ucfirst($type);
$path = JPath::find(
JModel::addIncludePath(),
JModel::_createFileName( ‘model’, array( ‘name’ => $type))
);
require_once $path;
$result = new $modelClass($config);
Where did we set the include path? it is done automatically in JControllers constructor:
$this->addModelPath($this->_basePath.DS.’models’);
This behavior matches what we have in part 0, where all the models are inside “/models” directory.
3. JModel.getTable()
This method by default would search for a JTable class having the same name as the model itself, eg:
SchoolModelTeacher.getTable() = new TableTeacher()
It can be seen very obviously here in the JMode and JTable code:
JModel:
$prefix = ‘Table’
$instance =& JTable::getInstance($name, $prefix, $config );
JTable:
$tableClass = $prefix.ucfirst($name);
$path=JPath::find(JTable::addIncludePath(), strtolower($type).’.php’)
$instance = new $tableClass($db);
Similar to how the JModel include path is added, JTable include path is automatically added in JModel’s constructor:
if (array_key_exists(’table_path’, $config)) {
$this->addTablePath($config['table_path']);
} else if (defined( ‘JPATH_COMPONENT_ADMINISTRATOR’ )){
$this->addTablePath(JPATH_COMPONENT_ADMINISTRATOR.DS.’tables’);
}
One interesting point we can see is it will only automatically load the JTable class from the administrator component. That’s why we only see JTables in the administrator component, but not the front end component. The actual reason is unknown for me.
4. JView.get($property)
This is another magic method, although we normally only call it by one way get(“data”). What it does is automatically construct the JModel with the same name and call the method “get[PROPERTY]” of that JModel. Eg:
SchoolViewTeachers.get(“data”) ==> SchoolModelTeachers.getData();
SchoolViewStudent.get(“name”) ==> SchoolModelStudent.getName();
The code that illustrate this is here (modified):
$model = $this->_defaultModel;
$method = ‘get’.ucfirst($property);
$result = $this->_models[$model]->$method();
Where does the “_defaultModel” coming? It is actually called from the “display” task of the JController:
$model = & $this->getModel($viewName)
$view->setModel($model, true);
So the overridden JView class can easily take out the correct data form the JModel and put into request then the controller would pick the correct layout and renders to the users.
5. JView.getModel()
This method DOES NOT CREATE a JModel object, instead, it just try to load the JModel from its models hash map, normally the default model is set when the “Display” method of JController is called.
6. JController.getModel()
This is where the JModel is really created everytime, it is the beginning point where JModel.getInstance is called:
$name = $this->getName();
$prefix = $this->getName() . ‘Model’;
$model = & $this->_createModel( $name, $prefix, $config )
7. JController.getView()
Simillar to above, this is where the JView objects are actually being created, based on the directory structure. The actual code is more complicated (as there is a more complicated directory structure), but serve the same function.





