Model-View-Controller

Other languages:
Bahasa Indonesia • ‎English • ‎Kiswahili • ‎Nederlands • ‎català • ‎español • ‎français • ‎italiano • ‎日本語

This page describes the Model-View-Controller design pattern as implemented in Joomla.

When Joomla starts to process a request from a user, such as a GET for a particular page or a POST containing form data, one of the first things that Joomla does is to analyse the URL to determine which component will be responsible for processing the request and hand control over to that component.

It will do this by running the entry point component PHP file for that component. If the component is called com_example, then Joomla will run:

If you are developing a component you could actually put all of your component code into those two example.php files. However, an advantage of following the Joomla MVC pattern is that you can make full use the Joomla library MVC classes, which greatly reduces the amount of code you need to write.

Joomla MVC Overview

Joomla MVC

Entry Point Code

The main role of the entry point PHP file (example.php for com_example) is to determine which controller to run. It does this based on the task parameter (described in more detail later) and involves:

Controller

The controller is responsible for analysing the user's request, checking that the user is allowed to perform that action and determining how to satisfy the request. The latter will involve:

View

The view specifies what should appear on the web page, and collates all the data necessary for outputting the HTTP response.

After the controller creates the view instance it calls the view's setModel() method and passes the model instance. In this way the view knows which model to use, and calls the model's methods to obtain the data required for returning to the user.

Layout

The view doesn't output HTML but delegates this to the layout. The layout contains PHP code which runs within the context of the method (usually display()) of the view, which means that if the view holds the response data in, for example, $this->items then the layout can access that same $this->items when it is outputting the HTML.

Separating the view and layout like this enables another level of flexibility, as you can easily set up a layout override to output the view data using your own preferred HTML.

Model

The model encapsulates the data used by the component. In most cases this data will come from a database, either the Joomla database, or some external database, but it is also possible for the model to obtain data from other sources, such as via a web services API running on another server. The model is also responsible for updating the database where appropriate. The purpose of the model is to isolate the controller and view from the details of how data is obtained or amended.

If the component is displaying a form which is defined in XML using the Joomla Form approach, the model handles the setting-up and configuration of the Form instance, ready for the layout to output fields using $form->renderField() etc.

Subsequent Processing

The output from the component (specifically the HTML output from the layout) is not directly output as the HTTP response, but rather is captured and buffered by Joomla. Once the layout has generated the output, the component hands control back to the Joomla framework which then loads and executes the template. The template combines the output from the component, and any modules that are active on the current page, so that it can be delivered to the browser as a single page.

The HTTP Request task Parameter

Joomla uses the HTTP Request task parameter to determine which controller should be used. The task parameter can be sent in an HTTP GET or an HTTP POST – in fact, Joomla doesn't really make a distinction between GET and POST parameters – but the task parameter is just an ordinary HTTP parameter, nothing special.

In the core Joomla entry point PHP files you'll almost always see something like:

$controller = JControllerLegacy::getInstance('example');
$controller->execute(JFactory::getApplication()->input->get('task'));

with example replaced by Contact, Content, Modules etc.

The getInstance() method of JControllerLegacy (or BaseController, (as it is now known after Joomla 3.8) is where all the magic happens. It

The next line of code ($controller->execute(JFactory::getApplication()->input->get('task'));) then calls the execute() method of the controller instance with the parameter which is now the method to run, and the execute method basically runs the passed-in method.

The task parameter is of the form x.y, where x represents the controller type and y the method to call. The controller type may be absent in which case the method in controller.php is run. If the controller type is present then one of the controllers in the controllers folder is used. If the task parameter is not set at all then the display() method in controller.php is run. The table below lists the possibilities for a component called com_example.

Form of task Controller file Controller class Controller method
controllerType.method controllers/controllerType.php ExampleControllerControllerType method
eg items.process controllers/items.php ExampleControllerItems process
method(no controllerType set) controller.php ExampleController method
(task not set) controller.php ExampleController display

The above is true both for the Frontend site and the Backend Administrator, except that for the Administrator it all happens under the administrator folder.

Post/Request/Get Pattern

Post-request-get1.jpg

Joomla follows the Post/Redirect/Get pattern, which means that when a user submits a form in an HTTP POST, then rather than Joomla responding to the POST with an HTML page, redirects to another page which the browser will access with an HTTP GET.

This is typified when the Administrator displays the Content/Articles page, as shown in the first diagram. The action to be performed is indicated by the task parameter, and both it and related data are sent in the POST request. Once the action is performed the next web page to be displayed is defined in the HTTP Redirect.

Post-request-get2.jpg

The second diagram depicts the pattern when an administrator edits an article. In this case there is the additional step of displaying the edit form, which again Joomla handles by sending an HTTP Redirect in response to the original request to edit an article. (At point 3 Joomla (in the BaseDatabaseModel) stores an edit id in the session and component controllers check this id at point 4 to ensure that users can't just specify the URL of the form directly without going through point 3).

The red numbers in green circles in the diagram refer to the different types of HTTP requests which Joomla is handling. We'll see in the next section that different Joomla MVC classes have been defined to cater to these five cases.

Joomla MVC Classes

There are several Joomla library MVC classes under libraries/src/MVC and this section aims to give an overview of these classes and explain when your own component should use each class. It doesn't attempt to provide a full description of each class's functionality.

MVC Base Classes

The 3 MVC base classes are BaseController (previously called JControllerLegacy), HtmlView (previously called JViewLegacy) and BaseDatabaseModel (previously called JModelLegacy). The functionality within BaseController includes:

The HtmlView class includes:

The BaseDatabaseModel contains:

In general, using base classes is a good option if your component is displaying a single item on a site page.

Higher-level View Classes

There are 3 higher-level view classes, all of which inherit directly from the HtmlView base class. The name of the class (and so the name of the PHP file) gives a good indication of its use:

Using the CategoryView or CategoriesView classes could be useful if you're following the paradigm of how com_content outputs this information on the site, but otherwise probably not so useful.

The CategoryFeedView class will help if you're providing a feed, as described in Adding a Feed.

Higher-level Controller Classes

There are 2 higher-level controller classes, each of which inherit from BaseController.

AdminController contains methods which handle the types of operations that can be performed on multiple items, for example:

However, note that it doesn't support the operations enabled by the Batch button on e.g. the Content/Articles page. The code generally calls the related model method to effect the operation, sets up the message based on the success of the model operation, and sets up the redirect back to the same page. For this reason it's very useful in case 2 shown in the diagrams above in Post/Request/Get pattern.

The name AdminController suggests that this controller is to be used only on the Backend Administrator functionality, however, this is not the case. It's appropriate to use it on the site Frontend as well.

FormController contains methods which are associated with editing an individual item

The FormController is thus well suited to cases 3 and 5 shown in the diagrams above in Post/Request/Get pattern.

Higher-level Model Classes

Model hierarchy.jpg

The diagram shows the inheritance tree of the Joomla library MVC models.

ItemModel is almost the same as BaseDatabaseModel. It just has an extra getStoreId() method which is relevant when you have a component and/or several modules sharing the same model and you want to distinguish between data sets relevant to each.

In addition to getStoreId(), ListModel has capability relating to obtaining a set of records for display on a web page, including support for pagination. Note that the pagination capability may still be slightly different between the Frontend and Backend – see this issue. The ListModel is useful for supporting case 1 in the above diagrams.

FormModel includes support for Joomla forms, both for setting up the form so that it can be displayed, and also so that the form data sent in the POST can be validated. In addition, it has methods for implementing checkin and checkout of database records. So it's suitable for handling cases 3 and 4 in the diagrams above.

AdminModel extends FormModel, so it has all the capability for handling forms, but in addition has methods for handling database updates – including capability for adding, updating and deleting records – as well as support for handling operations in batch. So it's suitable for handling cases 2 and 5 in the diagrams above. As with the AdminController, this model is not just appropriate for the administrator functionality, but can be used on the Frontend as well.

However, although the FormModel and AdminModel support different cases in the flow associated with editing a record, in practice it's common to use the same model for all the different steps of the flow. All the Joomla core components use the same model across these steps, and so they all extend AdminModel instead of FormModel.

Something to be aware of if you are using the same model across the "edit item" flow is that your model code is performing 2 purposes:

  1. preparing data to be shown on a web page
  2. preparing a form, either for display on a web page or for validating POST data

When you're using the model because you're handling a POST (i.e. cases 3 and 5 in the diagram) then any effort expended in preparing the data for a web page is going to be wasted. (In fact, in the FormController getModel() method call, the parameter $config is set to array('ignore_request' => true) by default, which results in the model's populateState method not being run, perhaps to save this wasted effort.)

Summary

As we've seen Joomla:

The choice of which controller and model classes to extend is easier on the Backend, because you just follow the pattern of the Joomla core components.

For the Frontend here's a rough guide:

Simply displaying a record or a set of records, without providing the ability to change anything:

Displaying a form with multiple records (but the form isn't defined in an XML file), including the providing the ability to select several records and apply some sort of operation to them (eg delete, publish):

Handling the HTTP POSTs from that form in subcontrollers:

Displaying a form with a single record, where the form is defined in an XML file, and allow the user to edit it, or a blank record and allowing the user to create a record:

Handling the HTTP POSTs from that form in subcontrollers:

See Also

Component Development Series

Developing an MVC Component for Joomla! 4.x

Developing an MVC Component for Joomla! 3.x



Top