Joomla Model-View-Controller Component – Part 4 – Creating an Administrator Interface


From Joomla! Official Documentation

Introduction

In the first three tutorials, we have developed a MVC component that retrieves its data from a table in the database. Currently, there is no way to add data to the database except to do it manually using another tool. In the next articles of this tutorial, we will develop an administrator section for our component which will make it possible to manage the entries in the database.

This article, Part 4 – Creating an Administrator Interface , will be an article with no new source code for our Hello component but will describe some basic details of the MVC pattern. In the frontend solution (site section) we developed the first part of our component. The frontend solution is based upon default Controllers, Views and Templates and you were “taken by the hand” and “left to trust” the default handling of the code. This is going to change in the Backend or Administration section of our Hello component – we will have to develop all of the code that manages the application flow.

Site / Admin

Joomla! is a content management system. The frontend is used for presenting the users with content and allows certain logged in users to manipulate the content. The backend is responsible for administrating the website framework (structuring / managing / controlling / maintaining). This division between (frontend) site-content and (backend) administration is a fundamental aspect of the Joomla! architecture.

Entrance points

From the XML file of our frontend example it was already obvious that there would be an administration part:

<?xml version="1.0" encoding="utf-8"?>
  ...
  <administration>
  <!--  Administration Menu Section -->
  <menu>Hello World!</menu>
  <!--  Administration Main File Copy Section -->
  <files folder="admin">
  <filename>hello.php</filename>
  <filename>index.html</filename>
  <filename>install.sql</filename>
  <filename>uninstall.sql</filename>
  </files>
  </administration>
  ...

Only the .sql files were of use and only during installation for our frontend view, the other two files have no content besides generating a blank page. Access your websites file system at your hosting provider (or on your own server) and browse through the directories after installing the frontend com_hello component. You may have noticed that our Hello component is to be found twice:

<root>/components/com_hello
<root>/administrator/components/com_hello

These two sub-directories link to the previously explained site-content and administration. Administrator interactions explicitly go via the administrator sub-directory, where guest or registered users will enter the default entrance on the root:

<root>/index.php

Administrative users will have to log in, and after logging in they will enter your site via:

<root>/administrator/index.php

With the different access points it is easy to grasp that with setting up the administrator section the naming conventions have no dependency with the site section. Whilst the MVC pattern is also applicable for the administrator section this implies that identical Controls, Views and Models naming can (and sometimes must) be used as in the site section.

MVC pattern interaction

In Developing a Model-View-Controller Component – Part 1 the figure on the right was used to explain the focus of the first three parts of this Developing a Model-View-Controller Component tutorial. Now we will use this figure to explain how decisions are made on what is going to be displayed and how to manipulate this.

Example roll-out

For explanation purposes an easy to grasp example will be used. A library has the main function of lending books to registered users. Simply laid out there are three tables:

  • users
  • books
  • relation

Lets keep it all very simple. The users are addressed by Id and Name. The books are identified by Id and Title and the relation contains both Ids and the date of lending.

The example is carefully chosen and will help in explaining the Joomla! architecture in more detail. The administrative side of our Hello component is not even that complex with only one table to manage. After the explanation of this chapter it should be easy to follow the tutorial in the succeeding chapters

Mapping a Joomla! MVC component from the example

In this example we will assume that administrative actions (add, edit, delete) are tasks that are to be performed by the administrator. For the frontend user only the view of the Relation table is interesting (“when do I have to bring back the books?”). This example shows the entire list and ignores all privacy stuff that could be taken care of by letting registered users only see their own books (Hint: if ($user->registered) {} ).

Just like our frontend Hello component, for this library component only the default view is being used in the frontend. It lists the relational table, left joining the other two tables to obtain a human readable list of lend books.

Alice | One flew over ... | 12 aug 2009
Alice | Celeb talk        | 12 aug 2009
Mark  | Joomla!           | 15 aug 2009

With respect to the administration part it is important to understand that we have one default and three dedicated views, each controlling three tasks:

  • <Component name default view>
  • User administration
    • Add
    • Change
    • Delete
  • Book administration
    • Add
    • Change
    • Delete
  • Relation administration
    • Add
    • Change
    • Delete

Controllers

The main controller of the admin section needs to differentiate between the different Adds, Changes or Deletes that are requested. This is taken care of by creating sub-controllers for each view for handling their specific tasks.

<root>/administrator/controller.php
<root>/administrator/controllers/users.php
<root>/administrator/controllers/books.php
<root>/administrator/controllers/relation.php

The controller is an important part of the MVC pattern. Not only does it take care of the requested tasks, it is also the initiator of instantiating the model with the same name and it is responsible for setting the view and the desired form for that view. The controller really justifies its name.

Within the controller it is good to make a difference between activating tasks (for example the edit selection from a menu) and resulting tasks (for example the result of an edit trigger is the posted data).

Typical controller functions look like:

function <activating task>()  // <-- edit, add, delete
{
    JRequest::setVar( 'view', '[<componentname> | users | books | relation ]' );
    JRequest::setVar( 'layout', 'default'  );     // <-- The default form is named here but in complex
                                                  //     views multiple layouts might be needed.
    parent::display();
}

function <resulting task>()  // <-- save, remove
{
        $model = $this->getModel('[<componentname> | users | books | relation ]');
        if(!$model->action() ) {    // <-- action could be delete() or store()
                $msg = JText::_( 'Error: Could not perform action' );
        } else {
                $msg = JText::_( 'Action executed' );
        }

        $this->setRedirect( 'index.php?option=<componentname>', $msg );
}

A controller takes care of all tasks for that dedicated controller. After completing a resulting task the module will return to the main administration entrance point for that component, the main controller with the default view. Activating tasks enforce a new view with a form to display after first defining it.

The explicit definition of the form within a view might raise some eyebrows but our examples are too simple. For the general understanding and consistency this field should mostly be default. In complex views multiple forms could be defined within one view.

Models

The Controllers interact with their equally named Model counter part. In the frontend view the Model was only used to retrieve data. The backend has more controllers and thus also more model files. The backend model files not only are responsible for delivering data to the viewer but also take care of tasks initiated from the controller. A good model contains all actions required to manage a single table in the database.

<root>/administrator/models/<componentname>.php
<root>/administrator/models/users.php
<root>/administrator/models/books.php
<root>/administrator/models/relation.php

Views

Separate views are of course also required. For views and subsequent forms no forced naming conventions are required (linking to views is taken care of in the controller). In the following listing the Administrative tasks are identified as a subset for the different views. This choice is totally random and maybe even non-logical but that doesn’t matter for the explanation. Just for example purposes I added also a different view, a delete view, that could be used for all the deletes for all administrative tasks asking an “Are you sure” display.

<root>/administrator/views/<componentname>/view.html.php    + .../tmpl/default.php
<root>/administrator/views/users/view.html.php    + .../tmpl/default.php
<root>/administrator/views/books/view.html.php    + .../tmpl/default.php
<root>/administrator/views/relation/view.html.php    + .../tmpl/default.php

<root>/administrator/views/delete/view.html.php    + .../tmpl/default.php

Note: In general it is good practice to maintain one form per view because the view.html.php still has to deliver the content. With some basic logic you can enable, disable certain content but if this logic is becoming too complex start considering splitting up the view.

Note: Sharing template parts amongst the different views (for uniform layouting of headers and titles of your component) can be done using the PHP include / require;. There is one slight problem … how to make the logical reference? In my modules I have a collector bin for general to use sniplets. Because it involved the views and forms I put this general bin in the views directory. The variable $pathToGeneralView needs to be defined somewhere in the first lines of your file and you have to make sure that the logical reference path is correct (the ‘..’s). In the following example the files marked with a ‘*’ use the following code:

./com_compname/views/general/navigate.header.php  <-- sniplet code for the header
./com_compname/views/general/navigate.footer.php  <-- sniplet code for the footer
./com_compname/views/mngtable1/view.html.php
./com_compname/views/mngtable1/tmpl/default.php *
./com_compname/views/mngtable2/view.html.php
./com_compname/views/mngtable2/tmpl/default.php *
$pathToGeneralView = strchr(dirname(__FILE__), dirname($_SERVER['SCRIPT_NAME']));
$pathToGeneralView = str_replace(dirname($_SERVER['SCRIPT_NAME']),'.',$pathToGeneralView );
$pathToGeneralView = $pathToGeneralView . "/../../general/";  <-- returning path from current position.
...
<?php require_once $pathToGeneralView . 'navigation.header.php'; ?>
<P>Do something
<?php require_once $pathToGeneralView . 'navigation.footer.php'; ?>

Note: Giving the forms logical instead of the default naming is of course handy when having a lot of different views. Having also that much default forms could make you easily loose oversight. On the other hand the view.html.php can not be renamed and you are always forced to look at the directory name for the view name you are working in.

Essential Interaction Parameters

Everything is in place:

  • main and dedicated controllers;
  • main and dedicated modules;
  • different views and their forms.

Just one big question remains: How to use them!

Three parameters are mandatory for letting Joomla! do its job:

  • option
  • controller
  • task

These three parameters are almost self explaining ;). The option part when developing a component is easy, always assign your component name to it. For component development consider this one as a constant, of course the Joomla! engine has more options than only components.

The controller and task parameters can be manipulated within your component anyway you want it to.

How it all works together

Looking at the simplified MVC picture Joomla! the logical flow of interaction goes the following way:

  1. What is my entrance point?
    • The Joomla! engine discovers a logged in administrator and sets the entrance point to <root>/administrator/index.php otherwise it wil go to the <root>/index.php entrance.
  2. What option is requested?
    • The Joomla! engine reads the option variable and discovers that a component named <componentname> is requested. The entrance point becomes: <root>/administrator/modules/com_<componentname>/<componentname>.php
  3. Is there need to access a dedicated controller?
    • The Joomla! engine reads the controller variable and discovers that a dedicated controller is required: <root>/administrator/modules/com_<componentname>/controllers/<dedicatedcontroller>.php
  4. Is there a task that needs to be addressed?
    • The identified controller is handed the task value as parameter.
  5. The Model is derived from the controller and instantiated.
  6. The View and Form are set in the controller and initiated to become active.

How to add interaction

Within HTML there are two common ways to interact with Joomla!:

  1. reference to a link
  2. form submission post / get

Link reference for the Joomla! engine

Remember the activating tasks and resulting tasks mentioned earlier? Most activating tasks are initiated by a link. In case of the Library example the site section overview could be copied to the admin section. This default view will now be extended and every cell will become a link for editing the specific database element.

Using the Library example, the template PHP code without looping control will contain the following code:

$link = JRoute::_( 'index.php?option=com_library&controller=users&task=edit&cid='. $row->idu );
echo "<td><a href=\"".$link."\">$row->name</a></td>";
$link = JRoute::_( 'index.php?option=com_library&controller=books&task=edit&cid='. $row->idb );
echo "<td><a href=\"".$link."\">$row->title</a></td>";
$link = JRoute::_( 'index.php?option=com_library&controller=relation&task=edit&cid='. $row->idr );
echo "<td><a href=\"".$link."\">$row->date</a></td>";

Within each clickable field the three mandatory parameters to manipulate MVC can be identified. In addition there is one user parameter for handling the correct index in the controller task (cid). These parameter are separated by ‘&’. Do not use spaces in your variables this might screw-up parameter handling in certain browsers. After looping all text entries will be clickable and trigger the corresponding controller with the correct row id in the associated table.

[Alice} | [One flew over ...] | [12 aug 2009]
[Alice] | [Celeb talk]        | [12 aug 2009]
[Mark]  | [Joomla!]           | [15 aug 2009]

Posting Form Data to the Joomla! Engine

After being initiated by an activating task, an input form view might be the result. The sniplet code below could be the result of clicking the first cell of the default component view that is clicked for editing ([Alice]:cid=3).

<form action="index.php" method="post">
  <input type="text" name="username" id="username" size="32" maxlength="250" value="<?php echo $this->user->name;?>" />

  <input type="submit" name="SubmitButton" value="Save" />

  <input type="hidden" name="option" value="com_library" />                  // <-- mandatory
  <input type="hidden" name="controller" value="hello" />                    // <-- mandatory
  <input type="hidden" name="task" value="save" />                           // <-- mandatory
  <input type="hidden" name="id" value="<?php echo $this->user->id; ?>" />   // <-- user parameter, index in database for [Alice]
</form>

The three Joomla! mandatory parameters are placed as hidden in the form. Hidden parameters are not shown in any way but will be added to the posting data.

Tip: when debugging this form, replace in the form tag method="post" temporarily with method="get". All posted parameters will be shown in the URL of your browser. If the module is working undo this change. For one reason it looks sharper without all the parameters being shown in the URL and you avoid motivating people to manipulate the browser URL themselves. Of course one can look at the source code but using Post instead of Get, but this eliminates the first 90% of the earth population. The other reason is more technical and the simple explanation is that post methods (i.e. method=”post”) can contain more (complex) data.

Remark: In some developed modules you may notice that developers have also added the view parameter. This is bad programming whilst the controller(s) should take care of the view and the form.

Conclusion

The use of the three mandatory parameters and the different access points are clarified. Let’s do something with this knowledge and extend the Hello component to the administrative section in the succeeding articles of this tutorial.

var gaJsHost = ((“https:” == document.location.protocol) ? “https://ssl.&#8221; : “http://www.&#8221;);
document.write(unescape(“%3Cscript src=’” + gaJsHost + “google-analytics.com/ga.js’ type=’text/javascript’%3E%3C/script%3E”));

try {
var pageTracker = _gat._getTracker(“UA-12043219-2″);
pageTracker._trackPageview();
} catch(err) {}

Joomla Model-View-Controller Component – Part 3 – Using the Database


From Joomla! Official Documentation

Introduction

In the first two tutorials, we showed you how to build a simple model-view-controller component. We had one view which retrieved data from a model (which was created in the 2nd tutorial). In this tutorial, we will be working with the model. Instead of the data being hard coded in the model, the model will retrieve the data from a table in the database.

This tutorial will demonstrate how to use the JDatabase class to retrieve data from the database.

Retrieving the Data

Our model currently has one method: getGreeting(). This method is very simple – all it does is return the hard-coded greeting.

To make things more interesting, we will load the greeting from a database table. We will demonstrate later how to create an SQL file and add the appropriate code to the XML manifest file so that the table and some sample data will be created when the component is installed. For now, we will simply replace our return statement with some code that will retrieve the greeting from the database and return it.

The first step is to obtain a reference to a database object. Since Joomla! uses the database for its normal operation, a database connection already exists; therefore, it is not necessary to create your own. A reference to the existing database can be obtained using:

$db =& JFactory::getDBO();

JFactory is a static class that is used to retrieve references to many of the system objects. More information about this class can be found in the API documentation JFactoryAPI.

The method name (getDBO) stands for get DataBase Object, and is easy and important to remember.

Now that we have obtained a reference to the database object, we can retrieve our data. We do this in two steps:

  • store our query in the database object
  • load the result

Our new getGreeting() method will therefore look like:

function getGreeting()
{
   $db =& JFactory::getDBO();

   $query = 'SELECT greeting FROM #__hello';
   $db->setQuery( $query );
   $greeting = $db->loadResult();

   return $greeting;
}

hello is the name of the table that we will create later, and greeting is the name of the field that stores the greetings. If you are not familiar with SQL, it would be helpful to take a tutorial or a lesson to get yourself up to speed. One such tutorial can be found at w3schools.

The $db->loadResult() method will execute the stored database query and return the first field of the first row of the result. See JDatabase API reference for more information about other load methods in the JDatabase class.

Creating the Installation SQL File

The Joomla! installer has built-in support for executing queries during component installation. These queries are all stored in a standard text file.

We will have three queries in our install file: the first will drop the table in case it already exists, the second will create the table with the appropriate fields, and the third will insert the data.

Here are our queries:

DROP TABLE IF EXISTS `#__hello`;

CREATE TABLE `#__hello` (
  `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `greeting` VARCHAR(25) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

INSERT INTO `#__hello` (`greeting`) VALUES ('Hello, World!'), ('Bonjour, Monde!'), ('Ciao, Mondo!');

You might find the prefix on the table names rather odd. Joomla! will replace this prefix with the prefix used by the current install. For most installs, this table will become jos_hello. This allows multiple installs of Joomla! to use the same database, and prevents collisions with other applications using the same table names (i.e. two applications might share a database, but might both require a ‘users’ table. This convention avoids problems.)

We have specified two fields in our database. The first field is id, and is called the ‘primary key’. The primary key of a database table is a field that is used to uniquely identify a record. This is often used to lookup rows in the database. The other field is greeting. This is the field that stores the greeting that is returned from the query that we used above.

We will save our installation queries in a file called install.sql. (Note: In the original version of this file, install.utf.sql was used – this was incorrect. Also see discussion.)

Creating the Uninstall SQL File

Though we might hope that people will never want to “uninstall” our component, it is important that if they do, nothing is left behind after uninstalling our component. Joomla! will look after deleting the files and directories that were created during the “install”, but we must manually include queries that will remove any tables that were added to the database. Since we have only created one table, we only need one query:

DROP TABLE IF EXISTS `#__hello`;

We will save this uninstall query in a file called uninstall.sql. (Note: In the original version of this file, uninstall.utf.sql was used – this was incorrect. Also see discussion.)

Updating our Install File

We need to change a few things in our install.xml file. First, we need to add our two new sql files to the list of files to install. Secondly, the SQL install files have to be placed in the admin directory. Thirdly, we need to tell the installer to execute the queries in our files on install and uninstall.

Our new file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<install type="component" version="1.5.0">
 <name>Hello</name>
 <!-- The following elements are optional and free of formatting conttraints -->
 <creationDate>2007-02-22</creationDate>
 <author>John Doe</author>
 <authorEmail>john.doe@example.org</authorEmail>
 <authorUrl>http://www.example.org</authorUrl>
 <copyright>Copyright Info</copyright>
 <license>License Info</license>
 <!--  The version string is recorded in the components table -->
 <version>3.01</version>
 <!-- The description is optional and defaults to the name -->
 <description>Description of the component ...</description>

 <!-- Site Main File Copy Section -->
 <!-- Note the folder attribute: This attribute describes the folder
      to copy FROM in the package to install therefore files copied
      in this section are copied from /site/ in the package -->
 <files folder="site">
  <filename>controller.php</filename>
  <filename>hello.php</filename>
  <filename>index.html</filename>
  <filename>models/hello.php</filename>
  <filename>models/index.html</filename>
  <filename>views/index.html</filename>
  <filename>views/hello/index.html</filename>
  <filename>views/hello/view.html.php</filename>
  <filename>views/hello/tmpl/default.php</filename>
  <filename>views/hello/tmpl/index.html</filename>
 </files>

 <install>
  <sql>
    <file charset="utf8" driver="mysql">install.sql</file>
  </sql>
 </install>
 <uninstall>
  <sql>
    <file charset="utf8" driver="mysql">uninstall.sql</file>
  </sql>
 </uninstall>

 <administration>
  <!-- Administration Menu Section -->
  <menu>Hello World!</menu>

  <!-- Administration Main File Copy Section -->
  <files folder="admin">
   <filename>hello.php</filename>
   <filename>index.html</filename>
   <filename>install.sql</filename>
   <filename>uninstall.sql</filename>
  </files>  

 </administration>
</install>

You will notice two attributes present on the <file> tags within the <install> and <uninstall> sections: charset and driver. The charset is the type of charset to use. The only valid charset is utf8. If you want to create install files for non-utf8 databases (for older version of MySQL), you should omit this attribute.

The driver attribute specifies which database the queries were written for. Currently, this can only be mysql, but in future versions of Joomla! there may be more database drivers available.

Joomla Model-View-Controller Component – Part 2 – Adding a Model


From Joomla! Official Documentation

Introduction

In the first tutorial of this series, creating a simple view-controller component using the Joomla! 1.5 CMS framework was demonstrated.

In the first tutorial, the greeting was hardcoded into the view. This doesn’t follow the MVC pattern exactly because the view is intended to only display the data, and not contain it.

In this second part of the tutorial we will demonstrate how to move this out of the view and into a model. In future tutorials we will demonstrate the power and flexibility that this design pattern provides.

Creating the Model

The concept of model gets its name because this class is intended to represent (or ‘model’) some entity. In our case, our first model will represent a ‘hello’, or a greeting. This is in line with our design thus far, because we have one view (‘hello’), which is a view of our greeting.

The naming convention for models in the Joomla! framework is that the class name starts with the name of the component (in our case ‘hello’, followed by ‘model’, followed by the model name. Therefore, our model class is called HelloModelHello.

At this point, we will only model one behaviour of our hello, and that is retrieving the greeting. We will thus have one method, called getGreeting(). It will simply return the string ‘Hello, World!’.

The code for the view at site/models/hello.php:

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

// No direct access

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

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

/**
 * Hello Model
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class HelloModelHello extends JModel
{
    /**
    * Gets the greeting
    * @return string The greeting to be displayed to the user
    */
    function getGreeting()
    {
        return 'Hello, World!';
    }
}

You will notice a line that starts with jimport. The jimport function is used to load files from the Joomla! framework that are required for our component. This particular statement will load the file /libraries/joomla/application/component/model.php. The ‘.’s are used as directory separators and the last part is the name of the file to load. All files are loaded relative to the libraries directory. This particular file contains the class definition for the JModel class, which is necessary because our model extends this class.

Now that we have created our model, we must modify our view so that it uses it to obtain the greeting.

Using the Model

The Joomla! framework is setup in such a way that the controller will automatically load the model that has the same name as the view and will push it into the view. Since our view is called ‘Hello’, our ‘Hello’ model will automatically be loaded and pushed into the view. Therefore, we can easily retrieve a reference to our model using the JView::getModel() method. (If the model had not followed this convention, we could have passed the model name to JView::getModel())

Our previous view code contained the lines:

$greeting = "<h1>Hello World!</h1>";

To take advantage of our model, we change this line to:

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

The complete view now looks like:

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

// No direct access

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

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

/**
 * HTML View class for the HelloWorld Component
 *
 * @package    HelloWorld
 */

class HelloViewHello extends JView
{
    function display($tpl = null)
    {
        $model = &$this->getModel();
        $greeting = $model->getGreeting();
        $this->assignRef( 'greeting',        $greeting );

        parent::display($tpl);
    }
}

Adding the File to the Package

All that remains is to add an entry to the XML file so that our new model will be copied. The Joomla! framework will look for our model in the models directory, so the entry for this file will look like (it should be added to the site section):

<filename>models/hello.php</filename>

Our new hello.xml file will look like:

<?xml version="1.0" encoding="utf-8"?>
<install type="component" version="1.5.0">
 <name>Hello</name>
 <!-- The following elements are optional and free of formatting conttraints -->
 <creationDate>2007-02-22</creationDate>
 <author>John Doe</author>
 <authorEmail>john.doe@example.org</authorEmail>
 <authorUrl>http://www.example.org</authorUrl>
 <copyright>Copyright Info</copyright>
 <license>License Info</license>
 <!--  The version string is recorded in the components table -->
 <version>1.01</version>
 <!-- The description is optional and defaults to the name -->
 <description>Description of the component ...</description>

 <!-- Site Main File Copy Section -->
 <!-- Note the folder attribute: This attribute describes the folder
      to copy FROM in the package to install therefore files copied
      in this section are copied from /site/ in the package -->
 <files folder="site">
  <filename>controller.php</filename>
  <filename>hello.php</filename>
  <filename>index.html</filename>
  <filename>models/hello.php</filename>
  <filename>models/index.html</filename>
  <filename>views/index.html</filename>
  <filename>views/hello/index.html</filename>
  <filename>views/hello/view.html.php</filename>
  <filename>views/hello/tmpl/default.php</filename>
  <filename>views/hello/tmpl/index.html</filename>
 </files>

 <administration>
  <!-- Administration Menu Section -->
  <menu>Hello World!</menu>

  <!-- Administration Main File Copy Section -->
  <files folder="admin">
   <filename>hello.php</filename>
   <filename>index.html</filename>
  </files>  

 </administration>
</install>

Conclusion

We now have a simple MVC component. Each element is very simple at this point, but provides a great deal of flexibility and power.


Joomla! Official Documentation

Follow

Get every new post delivered to your Inbox.

Join 723 other followers

%d bloggers like this: