J1.5

Developing a MVC Component/Basic Backend Framework

From Joomla! Documentation

< J1.5:Developing a MVC Component

The "J1.5" namespace is an archived namespace. This page contains information for a Joomla! version which is no longer supported. It exists only as a historical reference, it will not be improved and its content may be incomplete and/or contain broken links.

Introduction[edit]

This article focuses on the entry page/article for the administrator. Whilst the MVC pattern is the same as for the frontend user, this chapter will rapidly go though all steps and setup the backend counter part in the admin section. This article will only focus on setting up the Basic Framework with a list of all the Hellos but without user interaction. The actual user interaction is added in the succeeding article Developing a Model-View-Controller Component - Part 6 - Adding Backend Actions.

Tutorial specific naming[edit]

Within the next articles the explanation of this administrator section we will keep as close as possible to the component name. For the general overview, lists from the database, we will use Hellos as identification. The Hellos naming will be used for viewing and controlling multiple Hellos at once from the database. When selecting a single Hello for Editing or Adding we will use the singular Hello as naming for the Controller and View. This Admin Hello has no functional relation with the Site Hello (the only dependency is the database content, of course).

Where parts 1,2 and 3 of the MVC explanation were working in the site directory tree of com_hello, part 5 and 6 will focus on the admin directory tree. Part 5 and 6 will not add or change files in the site directory tree. Look at the XML file in the attached example of the full com_hello implementation. The XML configuration file will help you with the exact location of the different files being used in this and the following chapter.

Creating the Basic Framework[edit]

The basic framework of the administrator panel is very similar to the site portion. The main entry point for the administrator section of the component is hello.php. This file is identical to the hello.php file that was used in the site portion except the name of the controller it loads will be changed to HellosController. The default controller is also called controller.php and this file is identical to the default controller in the site portion, with the exception that the controller is named HellosController instead of HelloController. This difference is so that JController will by default load the hellos view, which will display a list of our greetings.

Here is the listing for hello.php:

<?php
/**
 * @package    Joomla.Tutorials
 * @subpackage Components
 * @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_5
 * @license    GNU/GPL
*/

// No direct access

defined( '_JEXEC' ) or die( 'Restricted access' );

// Require the base controller

require_once( JPATH_COMPONENT.DS.'controller.php' );

// 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 = '';
    }
}

// Create the controller
$classname    = 'HellosController'.$controller;
$controller   = new $classname( );

// Perform the Request task
$controller->execute( JRequest::getVar( 'task' ) );

// Redirect if set by the controller
$controller->redirect();

The view and model that we will start with is the hellos view and the hellos model. We will start with the model.

The Hellos Model[edit]

The Hellos Model will be very simple. The only operation that we currently need is the ability to retrieve the list of hellos from the database. This operation will be implemented in a method called getData().

The JModel class has a built in protected method called _getList(). This method can be used to simplify the task of retrieving a list of records from the database. We simply need to pass it the query and it will return the list of records.

At a later point in time, we might want to use our query from within another method. Therefore, we will create a private method called _buildQuery() which will return the query that will be passed to _getList(). This makes it easier to change the query as well since it is localized in one place.

Therefore we need two methods in our class: getData() and _buildQuery().

_buildQuery() simply returns the query. It looks like:

/**
 * Returns the query
 * @return string The query to be used to retrieve the rows from the database
 */
function _buildQuery()
{
    $query = ' SELECT * '
           . ' FROM #__hello '
    ;

    return $query;
}

getData() will obtain the query and retrieve the records from the database. Now it might happen that we need to retrieve this list of data twice in one page load. It would be a waste to have to query the database twice. Therefore, we will have this method store the data in a protected property so that on subsequent requests it can simply return the data it has already retrieved. This property will be called _data. (<-- Naming convention conflict. Private or Protected data should be preceded with a '_' but as this reference is returned to the view where this data is directly accessed, this data can only be considered as public.)

Here is the getData() method:

/**
 * Retrieves the hello data
 * @return array Array of objects containing the data from the database
 */
function getData()
{
    // Lets load the data if it doesn't already exist
    if (empty( $this->_data ))
    {
        $query = $this->_buildQuery();
        $this->_data = $this->_getList( $query );
    }

    return $this->_data;
}

The completed model looks like:

<?php
/**
 * Hellos Model for Hello World Component
 * 
 * @package    Joomla.Tutorials
 * @subpackage Components
 * @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_5
 * @license        GNU/GPL
 */

// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die();

jimport( 'joomla.application.component.model' );

/**
 * Hello Model
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class HellosModelHellos extends JModel
{
    /**
     * Hellos data array
     *
     * @var array
     */
    var $_data;

    /**
     * Returns the query
     * @return string The query to be used to retrieve the rows from the database
     */
    function _buildQuery()
    {
        $query = ' SELECT * '
            . ' FROM #__hello '
        ;
        return $query;
    }

    /**
     * Retrieves the hello data
     * @return array Array of objects containing the data from the database
     */
    function getData()
    {
        // Lets load the data if it doesn't already exist
        if (empty( $this->_data ))
        {
            $query = $this->_buildQuery();
            $this->_data = $this->_getList( $query );
        }

        return $this->_data;
    }
}

This file is saved as models/hellos.php.

The Hellos View[edit]

Now that we have a model to retrieve our data, we need to display it. This view will be fairly similar to the view from the site section as well.

Just as our model was automatically instantiated in the frontend, so is it in the administrator section. Methods that start with "get" [e.g. getData()] in the model can be accessed using the get() method of the JView class. So our view has three lines: one to retrieve the data from the model, one to push the data into the template, and one to invoke the display method to display the output. Thus we have:

<?php
/**
 * Hellos View for Hello World Component
 * 
 * @package    Joomla.Tutorials
 * @subpackage Components
 * @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_5
 * @license        GNU/GPL
 */

// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die();

jimport( 'joomla.application.component.view' );

/**
 * Hellos View
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class HellosViewHellos extends JView
{
    /**
     * Hellos view display method
     * @return void
     **/
    function display($tpl = null)
    {
        JToolBarHelper::title( JText::_( 'Hello Manager' ), 'generic.png' );
        JToolBarHelper::deleteList();
        JToolBarHelper::editListX();
        JToolBarHelper::addNewX();

        // Get data from the model
        $items =& $this->get( 'Data');

        $this->assignRef( 'items', $items );

        parent::display($tpl);
    }
}

This file is saved as views/hellos/view.html.php.

Look carefully at the almost hidden differences compared to site example. The data is stored in a variable that is encapsulated within the model. Because the data amount is huge due to using the very handy _getList(), the need for returning a reference instead of a value is obvious. This is handled in:

$items =& $this->get( 'Data');

Looking again at this line and you will notice another difference with respect to the site view.html.php. The calling of the model function is done implicitly. The actual model function name is getData(). In the site example you had to call following two lines:

$model =& $this->getModel();
$greeting = $model->getData();

Both lines are now taken care of by calling: $this->get( 'Data');. Under the surface of this get() the 'Data' is prefixed with 'get' so when using this function make sure the model functions are preceded with 'get'. This function can also be used in the site section. Keeping the data in the model and accessing it by reference, via get() methods, is the preferred way of getting data from the model.

The Hellos Template[edit]

The template will take the data pushed into it from the view and produce the output. We will display our output in a simple table. While the frontend template was very simple, in the administrator we will need a minimal amount of extra logic to handle looping through the data.

Here is our template:

<?php defined('_JEXEC') or die('Restricted access'); ?>
<form action="index.php" method="post" name="adminForm">
<div id="editcell">
    <table class="adminlist">
    <thead>
        <tr>
            <th width="5">
                <?php echo JText::_( 'ID' ); ?>
            </th>
            <th>
                <?php echo JText::_( 'Greeting' ); ?>
            </th>
        </tr>            
    </thead>
    <?php
    $k = 0;
    foreach ($this->items as &$row)
    {
        ?>
        <tr class="<?php echo "row" . $k; ?>">
            <td>
                <?php echo $row->id; ?>
            </td>
            <td>
                <?php echo $row->greeting; ?>
            </td>
        </tr>
        <?php
        $k = 1 - $k;
    }
    ?>
    </table>
</div>

<input type="hidden" name="option" value="com_hello" />
<input type="hidden" name="task" value="" />
<input type="hidden" name="boxchecked" value="0" />
<input type="hidden" name="controller" value="hello" />

</form>

This template is saved as views/hellos/tmpl/default.php.

You will notice that our output is enclosed in a form. Though this is not necessary now, it will be soon.

We have now completed the basic part of the first view. We have added five files to the admin section of our component:

  • hello.php
  • controller.php
  • models/hellos.php
  • views/hellos/view.html.php
  • views/hellos/tmpl/default.php

You can now add these files to the XML install file and give it a try!

Conclusion[edit]

We have now implemented a basic framework for the backend admin component. A list where all of the Hellos are displayed. The next chapter will extend this framework and add user interaction / database manipulation.

Contributors[edit]

  • staalanden
  • jamesconroyuk

Download[edit]

The full admin component can be downloaded at: com_hello4_01.