Creating a Custom Joomla Component

This article describes first steps towards the development of a custom Joomla component. There are many Joomla components available but depending on your use case it might be inevitable to develop an individual Joomla component.

If you are looking for a Joomla component that you would like to install on your website then Joomla Extension Directory is the place to go. With Joomla components you can enhance the functionality of your Joomla website and improve user experience. If there is no Joomla component available that fits your need then it might be an option to develop a custom Joomla component.

This article follows a hands-on approach towards the development of a Joomla component. A basic understanding of PHP and MySQL is required to follow along. The idea of the component is to display a list of smartphones in the Joomla frontend with a detail view for each device. Of course this could be realised with other components - it is just for illustration. I picked this example as it is common pattern: Afiliate marketers for instance often list products in a table or as a comparison tool to promote and earn a commission. Another example that could make use of such Joomla component is a estate agency that would like to list properties on the website.

Ok, let's start then. I guess you came accross the Joomla folder structure already. Each Joomla installation has a folder named "components" in which our component will go. Hence I create a folder named "com_smartphones" within the components folder. I add a file called smartphones.php to the new folder with the following content:

<?php
echo 123;

Ok, not really impressive so far but alright for a first start. Let's try to check the Joomla frontend for any output. You might know that urls in Joomla typically look like www.your-domain.com/index.php?option=com_smartphones - let's try this! This will typically result in an 404 error message saying the component was not found. I need to add the "com_smartphones" component to the Joomla database. Run the following SQL query to add it (check the jos_ prefix and adjust if necessary):

INSERT INTO `jos_extensions` (`name`, `type`, `element`, `folder`, `client_id`, `params`, `custom_data`, `system_data`, `manifest_cache`) VALUES
 ('com_smartphones', 'component', 'com_smartphones', '', 0, '', '', '', '{"name":"com_smartphones","type":"component"}'}');

I now go back to the Joolma frontend and check again with index.php?option=com_smartphones attached to the URL. This time the output 123 is displayed.

Creating the Folder-Structure for a Joomla Component

In web development a programming concept called MVC is quite popular - Joomla uses MVC as well. The basic idea is to organise the web application in 3 parts: The model can be understood as an interface with the database. The view generates the output that is visible to the user and the controller kind of organises everything. Joomla components should follow the MVC concept for several reason, one of them is the template override functionality. Therefore I modify our smartphones.php file:

<?php
defined('_JEXEC') or die;
$controller = JControllerLegacy::getInstance('Smartphones');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect(); 

At first '_JECEX' is checked and if not defined it terminates. This prevents that the file is called directly. In the previous version it was possible to call the file via www.your-domain.com/components/com_smartphones/smartphones.php. Then an object of SmartphonesController is created - the class will be defined later. The class can contain several functions which can be called explicitely via the task parameter.

As a next step I create a file called "controller.php" within the com_smartphones folder. This file will have the following content:

<?php
defined('_JEXEC') or die;
class SmartphonesController extends JControllerLegacy {
}

Again, a direct call of the file is prevented. Then the SmartphonesController class is defined and derived from the JLegacyController class. For the moment we leave the class empty.

When I refresh the frontend another error message will come up saying that a view "smartphones" is not defined. So I just create another folder called "views" within the "com_smartphones" folder. Inside the "views" folder another folder called "smartphones" is created. In this folder I then place a file called view.html.php with the follwoing content:

<?php
defined('_JEXEC') or die;
class SmartphonesViewSmartphones extends JViewLegacy {
}

We check the frontend again and end up with an error message saying default layout not defined. We then create a folder called "tmpl" in the "smartphones" view folder and define the default layout with a file called "default.php" within the tmpl folder. In the default.php file we just write:

<?php
defined('_JEXEC') or die;
echo 123;

By refreshing the display in the frontend again this should print "123". Congratulation, we have now created the basic structure for the Joomla component. As a next step we will look at how to display dynamic data from a database.

Displaying Database Content

I want to recall the objective of our component which was displaying a list of different smartphones in the frontend. You probably agree that it would not be beneficial to hardcode the list, in fact you could just have used a simple Joomla article to do this. We assume dynamic content and a database table would be the ideal media to store information about the smartphones. We will just create a database table called "jos_smartphones" with columns called name, manufacturer, ordering and price using the following SQL comand:

CREATE TABLE `jos_smartphones` (
 `id` int(11) NOT NULL,
 `name` varchar(255) NOT NULL,
 `manufacturer` varchar(255) NOT NULL,
 `price` float NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `jos_smartphones` (`id`, `name`, `manufacturer`, `price`) VALUES
 (1, 'TopPhone', 'ManufacturerA', 99)
 (2, 'CheapPhone', 'MassProuction', 14.99);
ALTER TABLE `jos_smartphones` ADD PRIMARY KEY (`id`);
ALTER TABLE `jos_smartphones` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;

This will also populate the table with some dummy data. Obviously this content should be displayed on the Joomla website. Therefore I modify the view.html.php file:

<?php
defined('_JEXEC') or die;
class SmartphonesViewSmartphones extends JViewLegacy { 
 public function display($tpl = null){
 $this->smartphones = $this->get('Smartphones');
 parent::display($tpl);
 }
}

I add a public function called "display" and within the function I call a function called "getSmartphones" which will be defined in the models files in a moment. This function will retrieve the smartphones and they are made available in the default.php file. Then the standard display function from the JViewLegacy class is called.
Note: The display function from the JViewLegacy class was called before we defined the function explicitely, we just added data to the view...

As the view is now calling a getSmartphones function I need to implement the function in the models. There I create another folder in the com_smartphones folder and name it "models". Within the models-folder I create a file called "smartphones.php" with the following content:

<?php
defined('_JEXEC') or die;
class SmartphonesModelSmartphones extends JModelList {
 public function getSmartphones() {
 $db = JFactory::getDBO();
 $query = $db->getQuery(true);
 $query->select('*');
 $query->from('#__smartphones');
 $db->setQuery((string) $query);
 $smartphones = $db->loadObjectList();
 return $smartphones;
 }
}

Within the function the Joomla API is used to establish a database connection and get the smartphones from the table. As a last step I modify the default.php file:

<?php
defined('_JEXEC') or die;
?>
<table>
 <?php foreach ($this->smartphones as $smartphone) { ?>
 <tr>
 <td width="300"><?php echo $smartphone->name; ?></td>
 <td width="300"><?php echo $smartphone->manufacturer; ?></td>
 <td width="300"><?php echo $smartphone->price; ?></td>
 </tr>
 <?php } ?>
</table>

When calling the frontend all the entries in the database should be displayed now. With this the first task is completed. As a next step the detail view for a single smartphone is created.

We now want to add a view to display a single smartphone, like a product page of a web shop. As a start we just duplicate the "smartphones" folder in the view folder and save it as "smartphone" folder in the view directory. We then modify the view.html.php in the new folder:

<?php
defined('_JEXEC') or die;
class SmartphonesViewSmartphones extends JViewLegacy { 
 public function display($tpl = null){
 $id = JFactory::getApplication()->input->getInt('id',0);
 $model = $this->getModel('smartphones');
 $this->smartphone = $model->getSmartphone($id);
 if(!isset($this->smartphone->name)){
 return JError::raiseError(403, 'ID not valid');
 }
 parent::display($tpl);
 }
}

We try to retrieve an input parameter called "id" and get the smartphone data for this id from the database. We raise an error if no data for the id is found. To access the model 'smartphones' within the view we need to override the default display function of the controller and add the following function to the controller:

public function display($cachable = false, $urlparams = false) { 
 $viewName = $this->input->get('view', $this->default_view);
 if ($viewName == 'smartphone') { 
 $viewLayout = $this->input->get('layout', 'default'); 
 $view = $this->getView($viewName, 'html', '',
 array('base_path' => $this->basePath,
 'layout' => $viewLayout)); 
 $view->setModel($this->getModel('smartphones'), true); 
 } 
 parent::display($cachable, $urlparams); 
}

We also need to add a function to the model to retrieve a single smartphone for a given id:

public function getSmartphone($id){
    $db = JFactory::getDBO();
    $query = $db->getQuery(true);
    $query->select('*');
    $query->from('#__smartphones');
    $query->where('id='.$id);
    $db->setQuery((string) $query);
 $smartphones = $db->loadObject();
    return $smartphones;
}

After this we can then modify the layout file and display the content of $this->smartphone->name for instance. When calling the url with index.php?option=com_smartphones&view=smartphone&id=1 the name should then be displayed in the frontend.

Adding Additional Functionality to the Joomla Component

Of course the previous steps are only a tiny snapshot of what can be realised with Joomla components. Usually components are added to the Joomla administration area as well. In the example mentioned above we could think of a backend to create, update and delete the smartphones listed in the database. Probably we would also like to assign our smartphone list to a menu. The Joomla API is quite powerful and many aspects of modern web applications such as different access levels, forms, SEF-Links, etc are supported. Pretty any web application can be realised as Joomla component. The integration into the Joomla website can also be realised within Joomla plugins or Joomla modules.

We are always happy to assisst you with the development of joomla components. Please get in contact with us for further information.