MVC Workflow With JPagination
MVC Workflow With JPagination
The MVC architecture is something that probably can not be explained without solid examples. In this
example we will concentrate on showing a list using pagination. We will assume a component called
"com_example" which just shows a single page with multiple items. If there are more items then
defined by the "List Limit" within the Global Configuration, pagination is added.
"com_example". Within the database table "#__components" a check is performed to see if the
component is active and if it is, Joomla! will call the entry-point file "example.php".
<?php
// File "example.php"
defined( '_JEXEC' ) or die( 'Restricted access' );
require_once JPATH_COMPONENT.DS.'controller.php';
First of all there is a security check on _JEXEC. After that we can start by including the controller-file
("components/com_example/controller.php") and initialize the controller. The controller-class
ExampleController just serves one purpose, there is only one task. There for we need not to pass any
$task to the execute() method. We even don't need the $controller->redirect() statement - we will
never set any redirects!
The controller-class is even more simple. We need to create it to tell Joomla! that we have a controller,
but it doesn't add anything to the JController-class.
<?php
// File "controller.php"
defined( '_JEXEC' ) or die( 'Restricted access' );
jimport('joomla.application.component.controller');
<?php
// File "views/items/view.html.php"
defined('_JEXEC') or die( 'Restricted access' );
jimport( 'joomla.application.component.view');
$items = $this->get('Data');
$this->assignRef( 'items', $items );
$pagination = $this->get('Pagination') ;
$this->assignRef( 'pagination', $pagination );
parent::display($tpl);
}
}
?>
The view-class is initialized in the normal way. From our view we then obtain data from the model by
using the shortcut-method $this->get('Data'). But instead of only importing $items from the model, we
also import $pagination.
<?php
// File "views/items/tmpl/default.php"
defined('_JEXEC') or die( 'Restricted access' );
?>
</table>
<?php endif; ?>
We can see now that the JPagination-object that we fetched from the model, contains two methods:
The "getPagesCounter()" method prints a little message saying something like "Page 1 of 2", while the
"getPagesLinks()" method prints the navigation box.
jimport('joomla.application.component.model');
function __construct() {}
function _loadData() {}
function getData() {}
function getTotal() {}
function getPagination() {}
}
?>
What you can see from this outline is that we need at least internal variables ($_data, $_total and
$_pagination) for the JPagination-trick to work. The variable $_data is an array containing all our items
that are going to be fetched from the database. It is initialized through the _loadData() function.
Because this array contains all the records from the table, we can also generate a $_total variable
which holds the total number of records found in the database.
Because we needed both the data ($_data) as a JPagination-object from the model (see the previous
chapter in this appendix) we define also a $_pagination variable. The $_data variable is a private
member but can be obtained from the model using the "getData()" method. The same goes for the
$_total variable which has a getTotal() method and the $_pagination variable which has a
getPagination() method. Later we will check if these are simple getters or if they contain a bit more
logic.
function __construct()
{
parent::__construct();
$application = JFactory::getApplication() ;
$config = JFactory::getConfig() ;
$this->setState('limitstart', $limitstart);
$this->setState('limit', $limit);
}
The $limit variable is first of all read from the Global Configurations "list.limit" option. To read this we
need to instantiate a JRegistry-object through JFactory::getConfig(). We set this as default, but we
could also allow an user to change the limit through some kind of selectbox. Because of this we want
check $_POST, $_GET and $_SESSION to see if the user defined its own list-limit. This is done
through the JApplication::getUserStateFromRequest() method.
Instead of setting the variables $limitstart and $limit just as private internal variables, they are saved
through the JModel::setState() method instead. The point of this is just a theoratical one: While $_data
and $_pagination can be seen as solid variables that are part of the data-model, the $limit and
$limitstart variables are seen as user-variables - which means the user could change these variables
when the right form-elements are available. If you don't believe this, forget about this and just use
private variables instead.
function _loadData()
{
if (empty($this->_data) && empty($this->_total))
{
$this->_data = $this->_db->loadObjectList();
$this->_total = count( $this->_data ) ;
return $this->_data ;
}
After we have filled $_data with the records from the database, we also calculate the total of records
and put it in $_total.
function getData()
{
$this->_loadData() ;
$limitstart = $this->getState('limitstart');
$limit = $this->getState('limit');
return array_slice( $this->_data, $limitstart, $limit );
}
But we don't want to return the full $_data array. We just want to return that part which is indicated by
the pagination: Either the first page or the page indicated by $limitstart. We simply use array_slice() to
return only the items needed.
function getTotal()
{
return $this->_total;
}
The getPagination() method starts with a call to _loadData(). It doesn't matter if we call getData() or
getPagination(). The first thing we do is get the data from the database and we only do it once.
The same applies to $_pagination. If there is no $_pagination available yet, we create it. Otherwise we
just return the existing object.
function getPagination()
{
$this->_loadData() ;
if (empty($this->_pagination))
{
jimport('joomla.html.pagination');
$limitstart = $this->getState('limitstart');
$limit = $this->getState('limit');
$total = $this->getTotal();
return $this->_pagination;
}
The magic of creating the actual JPagination-object just involves including the library-file through
jimport() and creating the object with the right arguments.