Modules

Creating a Site Module for Joomla 3.x - Part 6

Increasing Module Versatility

television icon 64x64pdf icon 64x64zip icon 64x64Sometimes you want your module to be able to display information in different ways and rather than writing different versions of the module to do this, we can use parameters that the administrator can set on the module to do this for us. Parameters make a module more user friendly by adding versatility to it. For example, if you wanted to give the user the option of laying out the information in a bulleted list or a group of paragraphs, you can do this with a parameter. Or maybe you want to give the administrator the ability to show more information in one instance of the module than in another instance, you can do this with parameters.

So, what is a module parameter really? A module parameter is a way to allow you to set variables on your module that the administrator can manipulate when they create an instance of the module that you can access programmatically. By examining the value of the parameters at runtime, we can make decisions based on what the values are.

Let’s create a simple parameter for our Random Quote module so that we can lay some groundwork that we will build on later. We will add a parameter that will allow the administrator to set the title of the module to the Author of the Quotes name. If this parameter is set to yes, then we will programmatically replace the module title with the Authors name and then omit the name from the body of the module, otherwise, we will display the module normally. We will accomplish this by using different views. Let’s get started.

It all starts with Form Fields

Joomla supports parameters for your extension through the use of form fields. Because of this, Joomla has a great number of form fields that are built in and available to the user. Form fields can be used in quite a number of places in your extension. To give you a couple examples, form fields can be used in the edit screen of a component allowing a user to enter in information that Joomla can then use or save to the database, and they can be used as part of your extension as parameters. The administrator can manipulate or set values to these parameters to make your extension more extensible and robust.

If you are familiar with HTML forms, then form fields should be old hat to you. Form fields are used extensively and Joomla is no exception. Joomla uses them, as stated above, in a lot of places. So useful are form fields that Joomla has a class devoted to them and extends their use to make things like validation much easier. To see a complete list of the form fields that Joomla supports please see the following web page.

https://docs.joomla.org/Form_field

Of this extensive list, the fields that would be most useful in our case would be either a select list or a radio button. I think since we are only talking about the choice of yes or no, the the radio field type will suit us just fine.

To add the parameter open the modules XML file and add the lines marked in red. To save space some of the file has been left out, marked by the ellipse you see just before the <files> tag. We will discuss these below.

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.5" client="site" method="upgrade">

<name>MOD_RANDOM_QUOTE</name>
<author>Joe Hildreth</author>
<creationDate>05 JUL 2016</creationDate>

...

<files>
<folder>language</folder>
<folder>tmpl</folder>
<folder>sql</folder>
<filename>helper.php</filename>
<filename>index.html</filename>
<filename module="mod_random_quote">mod_random_quote.php</filename>
<filename>mod_random_quote.xml</filename>
</files>

<config>
<fields name="params">
<fieldset name = "basic">
<field type = "radio"
name = "authortitle"
label = "MOD_RANDOM_QUOTE_PARAM_AUTHORTITLE"
default = "0"
description = "MOD_RANDOM_QUOTE_PARAM_AUTHORTITLE_DESC"
class = "btn-group btn-group-yesno">
<option value = "authortitle">JYES</option>
<option value = "0">JNO</option>
</field>
</fieldset>
</fields>
</config>

</extension>

Notice we have a whole new section added to the XML file all contained within the <config> tags. The <config> tag will hold all the fields associated with our parameters and is required for us to be able to use them. Next comes the <fields> tag. The <fields> tag takes one attribute called name. I am unsure of what the name tag is for. I think it either represents the params column in the modules table or perhaps it represents the $params variable to access the values. I will clarify this in the future if I am able to find out. The only thing I know for sure is that the name=”params” has to be there for parameters to work correctly in Joomla.

Next we come to the <fieldset> tag. Fieldsets allow us to break our parameters into logical groups and the name attribute of the tag tells Joomla where to place the fields on the manage module screen. If you use the attribute of name=”basic” the fields will be placed on the module tab of the module screen. If you use name=”advanced” the fields will be place on the Advanced tab of the module screen. Using any other value for this parameter causes Joomla to create a new tab in the module screen. If you do this, Joomla will look for a language string of COM_MODULES_<name>_FIELDSET_LABEL for the text to place on the tab. If the language string is not found, it will place the language string text on the tab in its place. The <name> portion of the language string will have the name that you put in the name attribute of the fieldset. For example if you used a fieldset tag that looks like the following:

<fieldset name=”myfieldset”>

Joomla will look for and use the language string of COM_MODULES_MYFIELDSET_FIELDSET_LABEL. To use this language string, you would place it in the language.ini file in your modules language folder.

Within the fieldset you will place all the fields that you wish to use. Remember, there are a bunch available to use, but in our case we are using a radio button. Each field has a number of attributes associated with it. Some attributes are required while others are not. To get the details for a particular field, go to the page listed above and on that page click the field you are interested in. In our case we want to use a radio button and if we click on the link we will be taken to the following page:

https://docs.joomla.org/Radio_form_field_type

On this page we see the all the requirements of using radio button form fields on our module. Take the time to look at the pages for different fields to get an idea of how they work. I will cover the radio button attributes now.

type=”radio” – The type attribute is mandatory and for a radio button must be set to radio to work.

name=”authortitle” – The name parameter is required and is the unique name of the field. This name will be used to store the parameter to the module table and will be used to access the value of the parameter.

label="MOD_RANDOM_QUOTE_PARAM_AUTHORTITLE" – The label is a mandatory attribute and is used to display the field’s label to the user. Like a lot of things with Joomla, the text of this attribute is translatable, so we use a language string here that will be translated in the language file. If no language string can be found it will use the text that it finds here as the label to the radio button.

default="0" – The default attribute is not mandatory but if used will tell Joomla which of the options is the default value and preselect it for the user.

description="MOD_RANDOM_QUOTE_PARAM_AUTHORTITLE_DESC" – The description attribute is an optional one and if used will be a description of what the parameter is used for. This is another attribute that is translatable and again we use a language string. If Joomla cannot find the language string it will use what ever text you place here.

class="btn-group btn-group-yesno" – The class attribute is optional but if used allows you to apply a CCS class to the form field. Joomla comes with bootstrap and in this case we are using two classes supplied with bootstrap to style our radio buttons. These styles place them in a button group and styles them with the Yes / No style. Using these styles allow our extension to have the same look and feel other Joomla extensions have.

<option> - The option tags of the radio button holds the values and the text of the selections we wish to present to the user. In our case there are only two, either they want to replace the module title with the author name or they do not. See below.

<option value = "authortitle">JYES</option>
<option value = "0">JNO</option>

The first line above gives the option of Yes. Again we see that the text to be displayed to the user is translatable. Here we are using a Language string that is built in with Joomla for Yes. The value attribute of the option tag will be the value that will be stored in the params field of the module table when the module is saved and will be the value that we check for in our code. The second line is similar to the first except we are using Joomla’s No language string and will store the value of 0.

Now that we have our parameter field in place in the manifest file, we need to add some translations to our language file so the end user can read the label and description. Save and close the manifest file and open the language INI file for editing. If you are following the tutorial as written this will be the language/en-GB/en-GB.mod_random_quote.ini file located in your project directory. Add the following text marked in red to the file.

; Translation strings for the Joomla system to use for user interface

; Translation strings for module in Admin area: Extensions | Modules
MOD_RANDOM_QUOTE="Random Quote"
MOD_RANDOM_QUOTE_DESCRIPTION="Displays a Random Quote."

; Translation Strings for module parameters
MOD_RANDOM_QUOTE_PARAM_AUTHORTITLE="Replace title with author?"
MOD_RANDOM_QUOTE_PARAM_AUTHORTITLE_DESC="Replace the title of the module with the Authors name."

Here we add a comment and two language strings to the INI language file. Recall the the INI language file holds the strings that the user will see during normal use of the Module, while the SYS.INI file holds strings that are used in certain parts of the administrator section of the module. The two language strings that we add here are the strings we placed in the radio field above.

(NOTE: If you have been following this tutorial as it has progressed your INI language file will be empty. I neglected to add the first two language stings when I done that tutorial. If your file does not have these, please add them now. These language strings are used when you are managing the module through the Extension | Manage area of the back end. Please accept my apologies.)

Checking our work

With the parameter and language stings added to the project I think it is a good time to check our work. Zip up the module and install it. When it has been installed click Extensions | Modules to get a list of the modules installed and then click on the Random Quote module. If all went well you should see the following.

014 001 Random Quote Module

On the edit screen of the Random Quote module, you will notice on the module tab that our radio button giving the user the selection of replacing the module title with the Author’s name is there. That’s great news, we also know that the translation strings are working because we are getting the string we provided for the label and the built in Joomla strings for Yes and No. But wait a minute, we wanted radio buttons and these look nothing like what we are used to. Well that is because we placed a class on the radio button using the available bootstrap classes. Looks pretty nice, don’t you think? To check that the description language tag is being translated, mouse over the label and look at the tooltip that pops up. You will see it there. Now, if you change the value of the parameter and save the changes, they will be written to the params field of Joomla’s module table for our module. Pretty cool, huh?

Accessing our parameter from code

Well, being able to create parameters that Joomla can save and give us access to is great but we need to be able to see what that value is and act upon it. Now we need to write the code that will allow us to do just that. However, before we do that we need to make a design decision.

In my mind, the user will decide whether they want the quote module to have the title they assigned it or it will be replaced with the author’s name. This will create two different ways of viewing the information we are wanting to show. So, to implement this, we will create an additional view called authortitle to go along with our already present default view. To decide which one to use, we will examine the authortitle parameter we set up and if the user selected yes, then we know that is the view we want to show. I will talk a little more on this when I get to the code.

The second option would be to access the parameter in the view and change it accordingly. This would work but I think it makes it a little more difficult for a person to style if there is more code in the view than really needs to be. Keep in mind though, either way will work just fine.

Picking at the entrails

When Joomla runs it creates the application object and a number of other useful objects that we can leverage to our own will. If in the modules PHP file we were to write a line like the one below, we would get a rather long list of variables that have been created and are accessible by our module.

var_dump(get_defined_vars());

Two of the objects created that are useful to us is a JRegistry object called $params and a PHP stdClass object called $module. So let’s take a look at them in turn.

$params – JRegistry Object

Joomla has a class called JRegistry that is a data store to hold application data and provides a number of methods to easily access the data contained in it. The JRegistry Class is used throughout Joomla to hold certain types of information. For example, the configuration file for Joomla can be accessed through the JRegistry Class. In our example, when the module is created, Joomla will create a new JRegistry object to hold the parameters of our module and assign it to the $params variable. To access the values stored in the $params variable we will need to use the Class Methods that JRegistry provides for us.

$module – stdClass Object

In addition to the $params variable above, Joomla will also create a PHP stdClass object and place in it information about our module. For example it will contain the title, the name of the module the position and other information. We are most interested in the title variable, as it holds the title assigned to the module and we can leverage this to change it if we want to.

If you are interested in exploring this more read on, otherwise skip to the next section. Go to your module and set the position to something like myposition, then create an article and place in the body of the article the following text.

Save the article and create a menu entry for it. When you load this article by clicking the menu link for it, it will load the module in the component area. We are doing this so that we have more room for the output of the module to display. Finally, in the modules PHP file add the line var_dump(get_defined_vars()); somewhere near the top. When the module runs you will see the list of defined variables that are available.

Putting it all together

At this point we have enough information to put it all to use. First we will create the new view. In the tmpl folder of your project directory create a file named authortitle.php and place the following code in it.

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

echo "<p>&quot;{$quote->quote}&quot;</p>";
echo "<p><em>&mdash; {$quote→source}</em></p>";

If you examine this file you will see that it is the same as the default.php file for the default view except we are not printing the author’s name. We only print the quote and the source. This is all we need to do here. Save and close the file.

Next open the components PHP file from your project directory and add the following code marked in red. I will cover what this does below.

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

// Include the mod_random_quote helper functions only once
require_once __DIR__ . '/helper.php';

$quote = ModRandomQuoteHelper::getRandomQuote();

// Determine which view to use, if no view is stored in the parameter we
// will set the value to 'default'
$view = $params->get('authortitle','default');

// If the view is set to authortitle, make some changes
if ($view == "authortitle") {
// Set the title of the module to the Author's Name
$module->title = $quote->name;
// Change the size of the header tag to prevent line wrapping
$params->set('header_tag','h4');
}

// If the authortitle was set to No, then the value of the parameter
// will be '0'. In this case we want to set the view to 'default'
if ($view == "0") {
$view = "default";
}

require JModuleHelper::getLayoutPath('mod_random_quote', $view);

I have commented the code above but we will cover it in detail.

$view = $params->get('authortitle','default');

First we get the view from our parameter. Remember, when we created the parameter we gave it a name of authortitle, and its value will be either authortitle or 0. If the module was installed but the user did not specifically set this parameter it will not be in the params field on the module table in the database. So to prevent something from going awry we use the JRegistry::get() method passing a second parameter. This parameter tells the method that if this variable does not exist then return the following value. In this case, if authortitle is not there it will return the value of default which is the name of the view we want to use if the module has not been set to replace the title with the author’s name.

if ($view == "authortitle") {

Next we check to see if our $view variable has the value of authortitle. If it does then we know that user wants to show the author’s name in the title.

$module->title = $quote->name;

Using the $module stdClass Object that Joomla provides us we set the module’s title to the author’s name we received from the database when we grabbed the random quote.

$params->set('header_tag','h4');

Finally, we use one of the other modules parameters and reduce the header tag from h3 to h4. This is only for aesthetics. When a longer name is printed using the h3 tag it will break across two lines. Reducing the size of the header helps prevent this from happening. Remember that the $params variable is a JRegistry object so we use the JRegistry::set() method to set the value of the header_tag variable to h4. If you are wondering were these other parameters are coming from, they are picked up in the Extension | Module area of the back end where you can set them for the module. Joomla makes it easy to change these parameters on the fly.

if ($view == "0") {

Next we check to see if the view is set to 0. Remember that if athortitle is turned off, the value saved is 0. I done this because for the bootstrap Yes/No class to work, the No value has to be 0. If we would have used a value of default, for example, both of our buttons would have been green. I only done it this way for appearance sake on the back end.

$view = "default";

If the value of authortitle was 0 then we know this is the default view, so we assign default to the variable.

require JModuleHelper::getLayoutPath('mod_random_quote', $view);

Lastly, we call the view. This code is identical to our last version except instead of calling a specific view on the second parameter, we instead use our $view variable. Now, it will get either the default view or the authortitle view based on the value of the $view variable which was set in the code above.

Testing our code

With the edits done to the modules PHP file, we can save and close it. Zip the project up and install it.

Go to Extensions | Modules and click on the Random Quote module. Make sure the Replace Title with Author parameter is set to No and click save. Now go to the front end and take a look. The title of the module should look normal with the title being set to Random Quote. Now go back to the back end and change the option to Yes and save it. Go to the front end and refresh the screen. You should now see the title of the module has been replaced with the name of the Author. See the image below.

014 002 Random Quote ModuleNotice that the name is smaller that the other module titles. Remember we set it smaller by changing the header_tag parameter to a h4.

Giving our extensions parameters gives us a lot of flexibility for our projects. Joomla makes it easy to add and access these parameters through fields added to the XML file and the $params JRegistry object that it creates for us when our module runs.

In the next module episode we will talk about versioning our module and how upgrades work. Thank you for taking the time and if you have any questions, feel free to go to http://www.myheap.com and use the contact link to send me a message. I will do my best to answer them.

END OF TUTORIAL

Creating a Site Module for Joomla 3.x – Part 5

The MVC Concept

television icon 64x64pdf icon 64x64zip icon 64x64Joomla components use the Model, View, Controller (MVC) pattern when they are written, and we will cover this in detail when we start writing components for Joomla. However, I just want to touch on the idea here just a little. When using a Model, View and Controller, your code is broken out into bits where each section of code is assigned a specific job to do. This makes maintaining the code easier because it is broken out in smaller chunks each having a specific purpose. So let me break down each function that the MVC pattern has.

First is the Controller. The controller should receive the users input, process it in some way and then act on it. Think of a remote for a DVD player. When you press the play button on the remote (controller), it sends the signals needed to the DVD player (the Model) to play the disk. The controller for a component in Joomla will examine the users input and then call methods in the model to get what it needs.

Next is the model. The Model’s job should be to retrieve data and return it. In our example above, when we press play on the DVD Remote (the controller), the controller tells the DVD player to get the video contents from the disk. The DVD player (the model) will access the disk and then start sending the data to your television, also known as the View. The model for a Joomla component will typically access the database and return the data to the controller.

Finally we have the view. The view’s job is to display the data that was returned from the controller. Continuing with our example from above, when the DVD player accesses the disk it will send the data that it retrieves to your television (the view). The television is only concerned about displaying the information to the end user. It does not care where the information came from or how it is retrieved. In a Joomla component the view is responsible for displaying the data that was returned from the model to the user.

Joomla modules on the other hand do not use Models, Views and Controllers in the classic sense, but the code can be broken down to resemble them and the end result is that the code is easier to debug and understand. We touched on this in part 3 of this tutorial series when we talked about the view or layout of the module. If you recall, we created the default view and called it statically from the modules PHP file. Later, when we start adding parameters to our module we will utilize other views for our module. So now that we understand what a view is for our module, what about the Controller and Model.

You can think of the modules PHP file as being the controller for the module. It is the file that Joomla calls when the module is loaded and this file will control getting the data it needs and passing that data to the view of the module. This leaves only to define a Model for the module.

If you examine the modules that are installed in Joomla you will discover that the PHP file for the module (the controller if you will) loads a helper class from another file. This helper class has the methods needed to get data from the database and returns it to the controller. This helper class can be thought of as a Model. It receives requests from the modules PHP file (the controller) and returns data based on that request back to the modules PHP file.

Some purist may say that I am being a little fast and loose with my definitions here, but the idea I am trying to pass along is that the MVC programming pattern does sort of fit into Joomla’s Module architecture and in the end will make coding and debugging our module easier. If for no other reason, it is broken into logical elements that make it easy to figure out where a problem is happening. If the data you are trying to display doesn’t look correct, you know that you should look in your view. If you are missing data, perhaps you should look in the helper class, etc.

Adding the Helper Class to our Module

To add the helper class to our module we need only to create a file to hold our helper class. If you look at the modules that are installed with Joomla you will see that this file is called helper.php and lives in that same directory as the modules PHP and XML file. Since standards matter for ease of portability and maintenance, we should not be any different. So in the root of your project directory create an empty helper.php file. Your project directory should look like the following with the addition of the helper file marked in red.

mod_random_quote/
mod_random_quote/helper.php
mod_random_quote/index.html
mod_random_quote/mod_random_quote.php
mod_random_quote/mod_random_quote.xml
mod_random_quote/language/
mod_random_quote/language/index.html
mod_random_quote/language/en-GB/
mod_random_quote/language/en-GB/index.html
mod_random_quote/language/en-GB/en-GB.mod_random_quote.ini
mod_random_quote/language/en-GB/en-GB.mod_random_quote.sys.ini
mod_random_quote/sql/
mod_random_quote/sql/index.html
mod_random_quote/sql/install.mysql.utf8.sql
mod_random_quote/sql/uninstall.mysql.utf8.sql
mod_random_quote/tmpl/
mod_random_quote/tmpl/default.php
mod_random_quote/tmpl/index.html

Now, open the helper.php file and add the following code:

<?php
/**
* Helper class for mod_random_quote module.
*/

abstract class ModRandomQuoteHelper {

public static function getRandomQuote() {
// database code goes here.
return "This is a returned quote.";
}
}

Now let’s discuss the code in this file briefly. We start with the <?php tag indicating this is a script and a comment that the contents of this file is the helper class for the mod_random_quote module. Next we define our helper class. The class name is composed of the module name in camel case with no underscores followed by the word Helper giving us the name of ModRandomQuoteHelper. Again, this is one of the conventions used in Joomla for naming classes. It is important to use this convention because there are parts of Joomla that create class names dynamically and this naming convention is used to derive the class name. Notice the class is created as an abstract class. This simply means that the class itself cannot be instantiated directly, and in our case we don’t need to. We only need a container to store our methods we want to use to access the data from the database. That brings us to the method declaration for getRandomQuote(). Notice it is public and static, meaning we can call this method without instantiating the class. We will flesh this file out more shortly, but for now notice that it simply returns a string that reads, “This is a returned quote.”. We will use this for testing before moving on to actually accessing the database to get a random quote.

In order to use our newly created class in our module, we will need to edit the modules PHP file to include it. Open mod_random_quote.php and make the additions marked in red.

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

// Include the mod_random_quote helper functions only once
require_once __DIR__ . '/helper.php';

$quote = ModRandomQuoteHelper::getRandomQuote();

require JModuleHelper::getLayoutPath('mod_random_quote', 'default');

The first line of code, require_once __DIR__ . '/helper.php';, will look in the current directory and load the helper class file. The require_once makes sure that we only import the code one time. Next we make a call to the method we created in the helper class to get the quote with the line of code that reads $quote = ModRandomQuoteHelper::getRandomQuote(); and assign it to the variable named $quote.

Now that we have the helper class written and the modules PHP file is calling the method we need to make a change to the template (or view) to make use of the data retrieved. Open the /tmpl/default.php file from your project directory and make the changes marked in red.

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

echo 'Random Quote Module';

echo '<br />';
echo $quote;

Here we have added a <br /> tag to add a line break and then echo our quote to the user.

With these changes in place we next need to update the manifest file so we can test. Open the mod_random_quote.xml file and add the line in red.

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.5" client="site" method="upgrade">

<name>MOD_RANDOM_QUOTE</name>
<author>Joe Hildreth</author>
<creationDate>05 JUL 2016</creationDate>
<copyright>(c)2016 Joe Hildreth, All rights Reserved</copyright>
<license>GNU General Public License V2 or later</license>
<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.<;/authorEmail>
<authorUrl>http://www.myheap.com</authorUrl>
<version>1.0.0</version>
<description>MOD_RANDOM_QUOTE_DESCRIPTION</description>

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

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

<files>
<folder>language</folder>
<folder>tmpl</folder>
<folder>sql</folder>
<filename>helper.php</filename>
<filename>index.html</filename>
<filename module="mod_random_quote">mod_random_quote.php</filename>
<filename>mod_random_quote.xml</filename>
</files>

</extension>

By now you have a grip on the manifest file and know that this line will include the file helper.php to be copied over when the module installs.

Testing the results

011 001 Joomla moduleZip up the module and install, publish it and give it a position and make it visible on all menus. The module should display like the image to the left. If all is well you should see the line, “This is a returned quote.”, indicating that our helper class was loaded and the method to return a quote was called and worked properly. If you had any issues, double check the content of your PHP and manifest files.

Getting a Quote from the Database

Now that we have the framework of our module in place by breaking out the functionality in different files, we can tackle getting one of our quotes from the database. Logically, getting information from the database is a job for the model, and in our module that means the helper class. Recall from above that we created a method in our class called getRandomQuote() whose job it will be to get a quote from the database.

Joomla has classes dedicated to working with the database and they are fairly simple to use. These classes are abstracted out and allow you to use the same code, regardless of the database server in which Joomla is running. These classes are JDatabaseDriver and JDatabaseQuery. The JDatabaseDriver class will return the connection to the database, creating one if it does not exist and is also responsible for returning the JDatabaseQuery object to make queries from the database. The JDatabaseDriver class object is available from JFactory. (For more information on JFactory see the Joomla execution cycle video or tutorial.) Let’s look at some code that will do this for us.

$db = JFactory::getDbo();

The above line of code will return the JDatabaseDriver object and store in in the variable $db. Pretty simple, don’t you think? Now that we have the database driver object, we can get a query object with the following code.

$query = $db->getQuery(true);

The above line of code will result in a new query object being returned and assigned to our variable called $query. Now, notice that we passed the value of true to the getQuery() method. This causes JDatabaseDriver to create a new empty query. If for some reason we needed to work with the last query made, we could pass false as a parameter to the method and JDatabaseDriver would return the last JDatabaseQuery object to us. For most practical purposes, we will always want a new empty query object and will pass true to this method. JDatabaseQuery object has lots of methods that help you create queries for accessing the database. These are probably best understood by example.

In our module, we want to get some random quote from the database. Well the first thing we need to figure out is how many quotes are there to work with. Fortunately, this is a simple query, all we have to do is select the count function on the table. The SQL code for this would look like this.

SELECT COUNT(*) FROM <tablename>;

Here <tablename> represents the table we want to do the count on. Creating the SQL with the JDatabaseQuery object is pretty simple and would use code like the following.

$query->select(“COUNT(*)”);
$query->from(“#__mod_random_quote”);

JDatabaseQuery allows us to build our queries in pieces and it takes the responsibility of assembling them together for us. The select() method aboves takes as a parameter the column names or SQL function (like count()) that we would use in a normal SQL SELECT statement. In this case we pass along the COUNT(*) function to it. Finally, the from() method takes as a parameter anything you would pass long in a regular SQL FROM statement. In this case, we are passing the database table of our module. Note that we have prefixed the table name with the #__ characters that Joomla will use to derive the database table prefix.

It should also be noted that these methods can be chained together. For example, the two lines of code above could be written as follows so feel free to pick your poison.

$query→select(“COUNT(*)”)->from(“#__mod_random_quote”);

With the JDatabaseQuery complete, we only need to pass this back to the JDatabaseDriver object like so.

$db->setQuery($query);

The setQuery() method will take the query that we created and store it in the database driver object. All that is left to do is have the driver execute and return the results to us.

There are a number of methods available to return the data from the database, and which one you use depends on the format of data you need returned back. Let me explain a little further. The methods available allow you to return a single result, a single row, multiple rows, a single column, data as an array, an associative array and as an object. The end result is that you have a lot of latitude with JDatabaseDriver. In our example we need only a single result, the number of rows in the table. We can do that with the following code.

$count = $db->loadResult();

The loadResult() method will return a single value from the database. In our case we executed the COUNT(*) function which returns the number of rows in the table which we expect only a single value. Once the value has been returned with loadResult() we assign it to the $count variable so that we can use it later.

To summarize, getting data from the database is pretty straight forward and for the most part we will always follow these same steps.

  1. Get the database driver from JFactory
  2. Get a Query object from the database driver
  3. Set up our query using the methods available from the JDatabaseQuery class
  4. Store the Query back into JDatabaseDriver
  5. Execute the query using the method that make sense for the data we expect to receive.

If you want to get a head start on using the database with Joomla, take the time to read the documentation which can be found at https://docs.joomla.org/Selecting_data_using_JDatabase

Now that we know how many rows are in the table, we can use this to select one randomly by using some php code like the following.

$recordNumber = rand(1, $count);

The above line of code will generate a random number between 1 and the number of rows we have in the table. In my database example from the last tutorial, this will be 50. Once we have this number then we can use it to select the specific record from the table. NOTE: The rand() function I am using above is a pseudo random number generator and does not generate cryptographically secure values, and should not be used for cryptographic purposes. Additionally, we assume that all the index, id values in the table are in sequential order with none missing. Since we ultimately have control over the data being stored in the database, we should experience no problems. But if, for example, we deleted a row from the table leaving that index empty, it is possible that the deleted index id would be randomized and then it not be in the database resulting in an error.

Now that we have the record number we want from the table, we can get a new Query object and create the query with the following code.

$query = $db->getQuery(true);
$query->select(“name, quote, source”);
$query->from(“#__mod_random_quote”);
$query->where(“id={$recordNumber}”);

The above code will generate the following SQL Query.

SELECT name, quote, source FROM #__mod_random_quote WHERE id=#

Keep in mind the following about the above query. Joomla will use your correct prefix for the table name above and the # I used after the id= is actually the random number we generated and assigned to $recordNumber.

With the Query out of the way, we expect only one row from the database to match our Query criteria, so we would want to use one of the methods from the JDatabaseDriver that returns a single row. We have a few to choose from. We can use loadRow(), loadAssoc() or loadObject(). Let me explain each briefly.

loadRow() will return one row from the database as an indexed array with the first column being at index zero. So a row would be accessed like the following:

$record[0]; //contains the name column value
$record[1]; // contains the quote column value
$record[2]; // contains the source column value

loadAssoc() is similar to loadRow() but it return the row as an associative array where each key is the column name. The row would be accessed like the following:

$record[‘name’]; //contains the name column value
$record[‘quote’]; // contains the quote column value
$record[‘source’]; // contains the source column value

Finally, loadObject() returns the row as a standard PHP object where each column will be accessed with the arrow operator. You can access the data like the following:

$record->name; //contains the name column value
$record->quote; //contains the quote column value
$record->source; //contains the source column value

Which method you choose really depend on how you plan to access the data in code. I will leave that as an exercise for you. Continuing with this example, I will use the loadObject() method. So to complete our code examples from above, we have the query finished and we need to submit the query to the JdatabaseDriver object and then execute the loadObject() method to retrieve the data. That can be accomplished with the following code.

$db->setQuery($query);
$record = $db->loadObject();

After executing the above code, the random quote will be loaded from the database and stored in the $record variable. Now let’s put it all together. Open the helper.php file and add the following lines marked in red.

<?php
/**
* Helper class for mod_random_quote module.
*/

abstract class ModRandomQuoteHelper {

public static function getRandomQuote() {
// database code goes here.

// Get the JDatabaseDriver object from JFactory
$db = JFactory::getDbo();

// Get the JDatabaseQuery object from the JDatabaseDriver object
$query = $db->getQuery(true);

// Build the query
$query->select("COUNT(*)");
$query->from("#__mod_random_quote");

// Save the query to the JDatabaseDriver object
$db->setQuery($query);

// Save the record count to a variable
$count = $db->loadResult();

// Randomize the record that we want
$recordNumber = rand(1, $count);

// Build the query for the record we want
$query = $db->getQuery(true);
$query->select("name, quote, source");
$query->from("#__mod_random_quote");
$query->where("id={$recordNumber}");

// Save the query to the JDatabaseDriver object
$db->setQuery($query);

// Load the row as a Standard PHP object from the database
$record = $db->loadObject();

// Return the row back to the caller
return $record;
}
}

Changing the view to show the quote

Up to this point we have made the connection to the database, grabbed our random quote and returned it to the caller. Remember we called our getRandomQuote() method from the modules PHP file and saved it to a variable named $quote. Then in the modules PHP file we call the template (or view) we wish to use. We need to update the view to use the $quote variable we returned from our helper. So open the /tmpl/default.php file and change it to the following.

<?php
defined('_JEXEC') or die;
echo "<p><b>{$quote->name}</b></p>";
echo "<p>&quot;{$quote->quote}&quot;</p>";
echo "<p><em>&mdash; {$quote->source}</em></p>";

Compared to the last version of this file we have removed the old echo statements and replaced it with three new ones. In the first line we display the authors name in bold. In the second line we display the quote wrapped in some quote marks and finally in the last line we display the source with a leading em-dash and a space. Save the file and let’s test out work.

Testing our work

011 002 Joomla moduleWe have not added any new files or folders since our last test so there is no need to make any changes to the module’s manifest file. All that we need to do is create a new archive and install it in the back end of Joomla. Remember to give it a module position, set it to published and set it to be visible on all menus in the event that you uninstalled it. If all went well your module should be displaying a quote like the image to the left. Click the home link a few times and you will see that the quote changes.

We have traveled a little way down the Joomla road in this series of tutorials, but we have much further to go and lots more exciting things to learn to write extensions for Joomla. In the next installment of writing a module for Joomla we will look at module parameters and how they are used. At this point though, we have a workable module, it works as designed and displays a random quote to the end user, but there are many things we can do to make it better and more robust. In the mean time do some reading on accessing the database with the link I gave you above. See you next time.

END OF TUTORIAL

Creating a Site Module for Joomla 3.x – Part 4

Creating a Database Table for Our Module

television icon 64x64pdf icon 64x64zip icon 64x64Our random quote module, to be of any use, needs to be able to have some data associated with it. While we could include all the quotes and sources and such in the code as some sort of data structure, it would over time be difficult to manage and update. It would be better if this kind of information could be held in a database table. In this lesson we will talk about a method we can use to create our database table, and the SQL that Joomla will need to have when we install our module to additionally create a table in the database and populate it with data.

This tutorial assumes you have some knowledge with working with a database and using database queries. If I get enough requests, I may be willing to create some tutorials on that subject matter. Let’s get started.

To begin with, our random quote module will display the name of the person the quote is from, the actual quote, and the source of the quote to our visiting guest on the front end of the site. Knowing this we will create a spreadsheet in LibreOffice Calc program with three columns called Name, Quote and Source. I have decided to use quote from the Founding Fathers of the United States of America. You can use what ever quotes you like, or you can download the source files of this tutorial from my website where you downloaded this document. Now, for each row, I will include the data for each quote. See the image below:

010 001 LibreOffice Calc

Continue adding quotes until you have as many as you want. (I stopped at fifty quotes.) Now save your spreadsheet in case you need it again later. (I saved mine as Founder Quotes.) The purpose of entering all this information in a spreadsheet is to have a simple way of getting a comma separated value (csv) file of the data. One of the features of phpMyAdmin is that you can use just such a file to enter data into a database table. Let’s continue then.

010 002 LibreOffice CalcTo save your spreadsheet as a comma separated values (csv) file, click File | Save As… from the menu. In the select box that reads “All Formats” select Text CSV (.csv) from the list, give it a filename and select the location you want to save it and finally click the save button. See the image to the left.

When LibreOffice Calc asks you about the document formatting, click the button that reads “Use Text CSV Format” Next the Export Text File window opens. Make sure the following options are set. Character set: Unicode (UTF-8), Field delimiter ‘,’ (a comma), Text delimiter ‘”’ (a double quote), Save cell content as shown is checked and Quote all text cells is checked. Then click the OK button to save the file. See the image below.

010 003 LibreOffice CalcWe now have our quotes saved in a comma separated value (csv) file. We can use this file to populate the database table that we will create in phpMyAdmin. So let’s do that next.

Creating a table with phpMyadmin

Open your browser and point it to http://joom.dev/phpmyadmin. If the page opens to show a bunch of warnings, remember we turned the error reporting on for PHP to the highest available level. Scroll to the bottom of the page and click the Ignore All button and they will go away. Now log into phpMyAdmin with your MySQL credentials. The user name of root and the password you saved from the LAMP tutorial. Now that you are logged into phpMyAdmin, on the left click the database that you created when you installed Joomla. (I named mine “joom3”). When you select the database on the left, all the tables associated with the database will be listed on the right hand side of the screen. Scroll to the bottom of the screen and you will see a form that will allow you to create a new table for the selected database. See the image below:

010 004 phpMyadmin

To create our table we want to take note of the prefix that is appended to all the tables in Joomla. Remember when we installed Joomla that we had the option of creating our own table prefix or use the random prefix that the installer came up with. I elected to use the random one that the Joomla installer picked. That prefix is the letters and underscore that you see at the beginning of each table name in Joomla’s database. In the Name field of the Create table form, enter in the prefix for your Joomla installation followed by mod_random_quote. So in my example you see that I named mine c12q4_mod_random_quote. It does not really matter what you call your table for your module but you will want to make sure that it doesn’t collide with one of Joomla’s tables or another extension you may install later. Since I have only one table for the module, I just named it the same as the module. Now for the number of column change it to read 4. Our table will have four columns, one for an index and the other three are for the Name, Quote and Source for our data that we have in our CSV file from the last step. Finally click the go button to instruct phpMyAdmin to create the table.

The next screen displays a form for us to create our table with where each column is a row in the form. As I stated earlier, we have four columns in our table. Fill out form as follows. For the first column set the Name to id, type is int, attributes is unsigned, index is primary, check the A.I. (Auto Index) checkbox and finally give the column a comment of index. For the second column of our table set the Name to name, type to varchar, length is 75 and comment to Author Name. For the third column set the Name to quote, type to text and the comment to Author Quote. Finally, for the fourth column of our table, set the Name to source, type to varchar, length to 200 and comment to Source Document. You can leave the collation to default and set the storage engine to InnoDB. If you like, you can enter a comment on the table. Maybe, Table for mod_random_quote or similar. Lastly, click the save button on the form. See the image below.

010 005 phpMyAdmin

Filling the table with our quotes

With the table created we can now import our CSV file into the table. With our table selected in Joomla’s database, click the Import tab at the top of the screen. The page displayed will give you the option of the type of data you wish to import into the table and some options of how and what to import. Start by clicking the Browse button in the file to import section and select your CSV file that you created earlier. The character set for the file should be set to UTF-8.

The Next section is labeled Partial import. Here we want to change the selector to 1, indicating we want to skip the first line of the file. Recall that the first line in our file has the field names, Name, Quote and Source.

The other options can be left alone and the section that reads file format should be CSV. Finally, we come to the last section of the page that reads Format-specific options, these can be left as they are except for column names. Our CSV file only contains three of the four columns of our table. So we need to map each of our columns as they appear in the CSV file to the table. We created the table in the same order as our CSV file so we enter in “name, quote, source”. These are the three columns our CSV file maps to and in that order. Finally, click the Go button to import our data. If everything was good you will see a successful message at the top of the screen. See the screen shots below:

010 006 phpMyAdmin

010 007 phpMyAdmin

010 008 phpMyAdmin

Exporting our table as a SQL file

Now that we have our data imported into the table we created, we could use it as is with our module. However, if we want to give our module to someone else we cannot expect the end user to create the table and import the data. We need a way of packaging it with our archive. To do this, we need a SQL file that we can use with our module that Joomla can use to both create the table and fill it with our quotes. Before we get into the intricacies of how all that works, let’s use phpMyAdmin to help us out by exporting our table a SQL file that we can later massage into our purposes.

Log into phpMyAdmin if you are not already. Select the Joomla database and then the table we created earlier. With the table selected, click the Export tab at the top of the page. PhpMyAdmin gives a lot of options as to how you can export data and the format that it is in. Fortunately, the defaults of the quick export method meets all of our needs. On this page under export method select quick. Make sure the format is set to SQL. That is all we need to do, click the go button to export the data. Your browser should prompt you to save the file. Be sure to move this file to your project directory so you don’t lose track of it. Also note that the file name will be the name of the table with a .sql on the end of it. See the image below.

010 009 phpMyAdmin

If you open the file that you just downloaded, you will see all the SQL command to create the table and insert the data into it. This is what Joomla will need to create and insert data into the table for us, only it will need to be modified a little so that Joomla can use the file. Let’s talk about Joomla and installing to the database next.

Joomla and the database

Joomla supports a growing number of databases including MySQL, MSSQL, PostgreSQL and more. However, we are only going to focus on MySQL in this tutorial. Joomla manages the installation, update and removal of tables and data for components through its manifest file. Each of these three options, install, update and uninstall [removing a table(s)] is controlled by a tag. I will cover them briefly.

The <install> tag will point to the SQL file Joomla will execute when it is installing an extension for the first time. This SQL file will create the tables and insert any data required into the tables for the extension to work. The <uninstall> tag will point to the SQL file Joomla will run when it is uninstalling an extension. This SQL file will be responsible for dropping the table from the database. Some developers do not drop their tables in the event a user wants to remove there extension and then reinstall it to fix a problem. Unless a user was playing with the code of the extension in question, I cannot think of any reason to leave the tables in the database. I think it would be better to remove them. Finally the <update> tag will point to the SQL files that would need to be run in order to update the extension to the current version. This is a topic that should be discussed in detail and we will do so when we start versioning of our component and do the first update. Now let’s add the files to our project that will enable us to install data into the database. We will go over these files in detail as we encounter them. Add the files and folders to your project marked in red.

mod_random_quote/
mod_random_quote/index.html
mod_random_quote/mod_random_quote.php
mod_random_quote/mod_random_quote.xml
mod_random_quote/language/
mod_random_quote/language/index.html
mod_random_quote/language/en-GB/
mod_random_quote/language/en-GB/index.html
mod_random_quote/language/en-GB/en-GB.mod_random_quote.ini
mod_random_quote/language/en-GB/en-GB.mod_random_quote.sys.ini
mod_random_quote/sql/
mod_random_quote/sql/index.html
mod_random_quote/sql/install.mysql.utf8.sql
mod_random_quote/sql/uninstall.mysql.utf8.sql
mod_random_quote/tmpl/
mod_random_quote/tmpl/default.php
mod_random_quote/tmpl/index.html

The sql folder will eventually hold all of our sql files to install, uninstall and update. For now though we are only concentrating on the first two. The index.html file, as you know, is to prevent the web server from displaying a directory listing. The other two files bear some discussion.

install.mysql.utf8.sql
uninstall.mysql.utf8.sql

These two files are executed when the extension is installed and uninstalled respectively and like most everything else with Joomla the filenames follow a predefined naming convention. I say that tongue in cheek because the manifest file explicitly names the files to run, but I think it is better to follow tradition. The filenames are made of the following segments. (un)install.<database-engine>.<file-encoding>.sql. So the install file for MySQL using UTF-8 encoding will be, install.mysql.utf8.sql, likewise an uninstall file for Microsoft SQL server using UTF-8 encoding will be uninstall.sqlsrv.utf8.sql.

Now that we have created the two empty files to hold the SQL commands that Joomla will need to execute when we install or uninstall our module, we need to populate these files with the actual SQL commands needed to do the job. Open the uninstall.mysql.utf8.sql file and add the following line to it and save the file.

DROP TABLE IF EXISTS `#__mod_random_quote`

This single line drops (or deletes) a table from the database if it exists. If you are observant you will have noticed that the prefix on the table start with the #__ characters (a pound sign followed by two underscore characters). Remember Joomla created a random table prefix for the tables when we installed. Because of this, we have no clue what another installed copy of Joomla would have used, so Joomla uses these special #__ characters as a macro of sorts. When Joomla sees this, it is replaced with the prefix of your tables. In my installation the tables are prefixes with c12q4_ so when Joomla runs this command it will drop a table named c12q4_mod_random_quote if it exists.

Now for the install file. Open the install.mysql.utf8.sql file and copy the contents of the SQL file you created with phpMyAdmin earlier and paste it into this file. Before we can use these SQL commands in Joomla we need to make some changes. Looking at the file, lines that start with -- and /* are comments, so feel free to delete them to make the file size a little smaller. Delete any lines that start with the key word “set”. What you should be left with is four SQL commands, One that creates a table, one that inserts the data and two that alter the table. In each of these commands you will see the name of the table that the command affects inside of backticks. Notice that when phpMyAdmin created this file it includes the table prefix as part of the table name. Mine, for example is c12q4_. Go through, either manually or using search and replace, and remove the prefix from the table name and replace it with the #__ characters. So, for example, I would change mine from `c12q4_mod_random_quote` to `#__mod_random_quote`. Recall from above, Joomla uses these characters as a macro so that your database table prefix is used. With all the changes made to the file save it.

Update the Manifest File

Open the mod_random_quote.xml file and add the following lines in red.

 

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.5" client="site" method="upgrade">

<name>MOD_RANDOM_QUOTE</name>
<author>Joe Hildreth</author>
<creationDate>01 JUL 2016</creationDate>
<copyright>(c)2016 Joe Hildreth, All rights Reserved</copyright>
<license>GNU General Public License V2 or later</license>
<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.</authorEmail>
<authorUrl>http://www.myheap.com</authorUrl>
<version>1.0.0</version>
<description>MOD_RANDOM_QUOTE_DESCRIPTION</description>

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

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

<files>
<folder>language</folder>
<folder>sql</folder>
<folder>tmpl</folder>
<filename module="mod_random_quote">mod_random_quote.php</filename>
<filename>mod_random_quote.xml</filename>
<filename>index.html</filename>
</files>

</extension>

Having some practice with these files, you know that the <folder> tag will copy over the sql folder and its contents. New, however, are the <install> and <uninstall> tags. I wrote briefly about them above, but I will recap. Recall that Joomla can use several databases and can create tables and data for those databases. When we install the module for the first time, the file pointed to inside the <install> tags will be run. Joomla will look for the driver that matches it current running database server and run the SQL file pointed to by the <file> tag. So examining the code above, we see there are two attributes included on the file tag. These attributes are driver and charset. The driver attribute identifies the database server that the included file is intended to run on and the charset identifies what character encoding the file is in. So above we see that the file inside the file tag above is written using utf8 encoding and is intended to be run on a MySQL server. Supporting other database servers only entails creating the SQL file for the install and adding another file tag with the driver and encoding listed. For example, a file for Microsoft SQL Server would look something like the following:

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

Testing our work

Before we can test our work, we need to delete the table we created earlier from the Joomla database. To do so, log into phpMyAdmin and select the Joomla database on the left hand column of the screen. On the right hand side of the screen, locate the table and click the drop button in the same row as the table name. (Be sure you are dropping the correct one.) The phpMyAdmin application will ask you to confirm that you want to delete the table. Click the OK button to finish the job. See the screen image below.

010 010 phpMyAdmin

With the files created and and the manifest updated to include our new files, zip the project up and install it on your development Joomla site. Now, open up phpMyAdmin and confirm that Joomla created the database table. Once you are satisfied, uninstall the module and then go back to phpMyAdmin and confirm that the table was deleted.

That concludes this tutorial. In the next we will continue to develop the module by adding code to talk to the database and displaying a random quote.

END OF TUTORIAL

Creating a Site Module for Joomla 3.x - Part 3

Where are we going?

television icon 64x64pdf icon 64x64zip icon 64x64Now that we have written a minimalist module for Joomla, let’s move on to do something a little more useful than printing “Welcome to my module!” to the screen. If you are asking why did I start with that, well the answer is, in short, it provides us a template in which we can copy over and use as the basis of a new module, a tool of sorts. Anything that saves a little time is a good thing, right.

Now, to get back on track. The module we are going to write is a random quote module and over the course of writing it we will cover database access, views or layouts, helper files, module parameters, and other tidbits along the way. Of course, this will happen over a few tutorials, but by the end of it, you should have a good grasp on how to write about any type of module you like.

Lay the foundation

Remember our basic minimalist module? Well create a new folder where were ever you keep your Joomla projects called mod_random_quote, and copy your three minimalist files to this folder. To recap, that should be index.html, mod_smallest.php and mod_smallest.xml, (or whatever you called your module if you deviated from the tutorials) Rename the PHP and XML files to mod_random_quote.php and mod_random_quote.xml respectively. Next, open the mod_random_quote.xml file and make the following changes marked in red.

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.5" client="site" method="upgrade">

<name>Random Quote</name>
<author>Joe Hildreth</author>
<creationDate>05 JUL 2016</creationDate>
<copyright>(c)2016 Joe Hildreth, All rights Reserved</copyright>
<license>GNU General Public License V2 or later</license>
<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.<;/authorEmail>
<authorUrl>http://www.myheap.com</authorUrl>
<version>1.0.0</version>

<description>Displays a Random Quote</description>

<files>
<filename module="mod_random_quote">mod_random_quote.php</filename>
<filename>mod_random_quote.xml</filename>
<filename>index.html</filename>
</files>

</extension>

In the above code we changed some of the data to represent our new module. Now, you have to admit that we saved a little time the with cut and paste and a few edits. Don’t forget, you can change the meta-data between the <name> and <description> tag to anything you like. With your edits made, save the file and create an archive. Install it into Joomla. Set a position and test it to make sure all is good. If not, look for errors in your manifest file, as this will usually be the cause of a problem at this stage. When all is well and good let’s take the next step.

Adding a Language File

One of the cool features about Joomla is it’s ability to cater to many different languages through the use of language files, and there is no reason our module should be any different. Even if you don’t speak another language, by breaking out certain parts of your module to use language strings you allow someone else to translate your module into another language, and it is simple to do.

Before discussing the actual language files, let’s first talk about where they are stored in the file system. If you look in the root of the site application file system you will see a folder called language and upon examining the contents of this folder you will see that a folder exists for each language installed. The naming convention for these folders consist of two lowercase letters followed by a dash and then two uppercase letters. These letters have the following meaning. The first two letters are the international standardized code for a language. For example, en = English, de = German, nl = Dutch, etc. The second two letters represent a dialect if one exists, for example en-GB means English of the Great Brittan dialect, en-US means English of the United States dialect. You get the idea.

My installed copy of Joomla, was installed with the en-GB language files, so if you open the en-GB folder you will see quite a few files located there. All of these files follow a naming convention that looks something like en-GB.<name-of-extention>.ini and en-GB.<name-of-extension>.sys.ini. These two files, the .ini and the .sys.ini are used in different areas of Joomla. The .ini files hold the translation strings for your extension that the end user will see. The .sys.ini file holds the translation strings that are used by Joomla itself. To clarify, the .sys.ini file will hold translations for the following:

  1. During the extension's installation, to allow localizing the post-installation messages,
  2. to build the administrator Components menu,
  3. to localize component parameters and menu parameters
  4. and in the Extension Manager→Manage screen.

And the .ini file will hold everything else. Don’t worry too much on it, I will clarify as we go along. We will also see the same thing in the administrator application on the back end. See administrator/language from your root web folder.

Along with these locations, you can also store your language files inside your extension's folder as well. For example we would have mod_random_quote/language/en-GB/en-GB.mod_random_quote.ini and .sys.ini files.

Joomla can read these language files from either location, so the real question becomes, which do I choose? There is some debate but the general consensus is to keep your language files with your extension and leave the global language files for the Joomla CMS. That is the method we will use in this tutorial. If you would like to know more about Joomla’s Language files, please see https://docs.joomla.org/Specification_of_language_files.

Now, go to your module’s project folder and create the following folders and files until your directory tree looks like the following:

mod_random_quote/
mod_random_quote/index.html
mod_random_quote/mod_random_quote.php
mod_random_quote/mod_random_quote.xml
mod_random_quote/language/
mod_random_quote/language/index.html
mod_random_quote/language/en-GB/
mod_random_quote/language/en-GB/index.html
mod_random_quote/language/en-GB/en-GB.mod_random_quote.ini
mod_random_quote/language/en-GB/en-GB.mod_random_quote.sys.ini

Take notice that we have added an index.html file to every folder to prevent the web server from listing the contents of a folder when there is no default file available. I just copied and pasted mine from the mod_random_quote folder.

When I discussed the manifest file in previous tutorials, I mentioned that the <name> and <description> tags were translatable. Joomla will use a translation string, if one is available to display this text, if not, it will use the text that is between the opening and closing tags. These strings are used by Joomla when you are managing the extension, so this gives us a hint to which language file the string belongs in. Open your manifest file and make the following changes:

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.5" client="site" method="upgrade">

<name>MOD_RANDOM_QUOTE</name>
<author>Joe Hildreth</author>
<creationDate>05 JUL 2016</creationDate>
<copyright>(c)2016 Joe Hildreth, All rights Reserved</copyright>
<license>GNU General Public License V2 or later</license>
<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.<;/authorEmail>
<authorUrl>http://www.myheap.com</authorUrl>
<version>1.0.0</version>

<description>MOD_RANDOM_QUOTE_DESCRIPTION</description>

<files>
<filename module="mod_random_quote">mod_random_quote.php</filename>
<filename>mod_random_quote.xml</filename>
<filename>index.html</filename>
</files>

</extension>

In the above file we have changed the name and description strings to MOD_RANDOM_QUOTE and MOD_RANDOM_QUOTE_DESCRIPTION. There are a couple of things to take note of here. Standard practice is to start your translation strings with the name of your extension to prevent name-space collisions with other extensions. In this example MOD_RANDOM_QUOTE and to append to them text that describes what the string is for. For example MOD_RANDOM_QUOTE_DESCRIPTION. The other thing to take note is that language strings are always written in upper case letters and words are separated with the underscore character. You may not use spaces in your language strings. There are a few other restrictions and I encourage you to read the docs on language files located at https://docs.joomla.org/Specification_of_language_files.

After you install your module, Joomla will look for these two strings in the .sys.ini language file for the users selected language and if they exist will replace the language strings with the string from the language file. If it cannot find the string, it will use the COM_RANDOM_QUOTE… string in the manifest file. So now, lets add our strings to the .sys.ini file. Open the following file:

mod_random_quote/language/en-GB/en-GB.mod_random_quote.sys.ini

and add the following to it.

; Translation strings for the Joomla system to use
MOD_RANDOM_QUOTE="Random Quote"
MOD_RANDOM_QUOTE_DESCRIPTION="Displays a Random Quote."

You can use comments in your language files but they must start with a semi-colon and are single line comments. So the first line is a comment to remind us that this language file exists to hold language strings for the Joomla System or CMS. The next two lines contain the strings we used in the manifest file and they are set to whatever English string we wanted to be displayed.

If you wanted to support another language with your component, it is as simple as creating a folder under the language folder following the naming convention and create these same two files. For example, say I want to support German, I would create the following files:

mod_random_quote/language/de-DE/
mod_random_quote/language/de-DE/index.html
mod_random_quote/language/de-DE/de-DE.mod_random_quote.ini
mod_random_quote/language/de-DE/de-DE.mod_random_quote.sys.ini

And the de-DE.mod_random_quote.sys.ini file would contain the following

; Translation strings for the Joomla system to use
MOD_RANDOM_QUOTE="Zufalls-Zitat"
MOD_RANDOM_QUOTE_DESCRIPTION="Zeigen Sie ein zufälliges Zitat."

Above, the language strings contain the German strings that we want to use in our module. (NOTE: I do not speak German, and the strings above were created with Google Translate.)

Now that we have finished adding our language strings we need to tell Joomla to install them with the rest of our module. To do that, open your manifest file and add the line in red.

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.5" client="site" method="upgrade">

<name>MOD_RANDOM_QUOTE</name>
<author>Joe Hildreth</author>
<creationDate>05 JUL 2016</creationDate>
<copyright>(c)2016 Joe Hildreth, All rights Reserved</copyright>
<license>GNU General Public License V2 or later</license>
<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.<;/authorEmail>
<authorUrl>http://www.myheap.com</authorUrl>
<version>1.0.0</version>
<description>MOD_RANDOM_QUOTE_DESCRIPTION</description>

<files>
<folder>language</folder>
<filename module="mod_random_quote">mod_random_quote.php</filename>
<filename>mod_random_quote.xml</filename>
<filename>index.html</filename>
</files>

</extension>

 

Recall that the files section of the manifest tells Joomla the files that need to be copied to the front end of our extension. Up to this point we used the tag <filename> to tell Joomla the individual file that we want to copy. If we had to do a single file at a time this section would grow quite fast, but fortunately, Joomla allows us to specify folders too. The <folder> tag names a folder that you wish to copy over. Joomla will create the folder and copy all of its contents to the module’s folder on the site application. It will make the copy recursive meaning that it will get any sub folders and their contents as well.

That is all there is to adding Multi-Language support to your Joomla extension. Simply create a folder to hold the language files in and create the .ini and .sys.ini files for the translations. Joomla will load the correct strings based on the selected language of the user and the default language that Joomla was installed with. Using language strings in your module itself is pretty simple too. You use a method called JText::_() with the language string as a parameter and Joomla will insert the proper language text for you. We will cover that more later.

Checking our work

We have made the necessary changes to our module to support internationalization. Let’s check our work before we move on. Go to your projects folder and create an archive of your module being sure to include the language folder that we added. Go to the back end and install the updated module. If you get any errors installing, be sure to check your manifest file for errors.

With the module installed, navigate to the manage screen, you should see your module listed as before and when you mouse over the module name you should see the description. If instead you see the language string you provided in the Manifest file for either the name or the description, you may want to check the following:

  1. Make sure the string you used in the manifest file matches the string you used in the language file.
  2. Make sure that you have the language strings in the correct language file. They should be in en-GB.mod_random_quote.sys.ini file.
  3. Make sure you have given the correct name to the .sys.ini file itself. If misnamed, Joomla cannot find the file.

A view from a different angle

Joomla supports what is called layouts. Layouts allow you to display the information you want in different views. Say, for example, you sell books and every week you have a sale and you use a module to display the list of books on sale. Now maybe on the homepage you want them displayed as a simple list, but on other pages you would like them to display as a list with a note of the sale price. Well, the good news is that you do not have to write separate modules to do these separate tasks. You can make your module display itself differently based on some parameters. We will get into just this scenario later, but for now, you need to know that Joomla can do it. Now, if our module is called with no specific view (or layout) then Joomla looks for one called default. Like everything else with Joomla, there is a file layout that we have to follow for it to work correctly. Additionally, there is some code that we need to add so that Joomla knows which view or layout we want. To get started, add the following folder and files to your project marked in red.

mod_random_quote/
mod_random_quote/index.html
mod_random_quote/mod_random_quote.php
mod_random_quote/mod_random_quote.xml
mod_random_quote/language/
mod_random_quote/language/index.html
mod_random_quote/language/en-GB/
mod_random_quote/language/en-GB/index.html
mod_random_quote/language/en-GB/en-GB.mod_random_quote.ini
mod_random_quote/language/en-GB/en-GB.mod_random_quote.sys.ini
mod_random_quote/tmpl/
mod_random_quote/tmpl/default.php
mod_random_quote/tmpl/index.html

Create a folder named tmpl (In my mind this folder is shorthand for template.) in your project file and copy your empty html file to it. Then make an empty file called default.php. Now open the default.php file and add the following code.

<?php
defined(‘_JEXEC’) or die;

echo ‘Random Quote Module’;

Save the file and close it. The code above first checks that it is being executed inside Joomla by checking if the _JEXEC constant has been defined, and if it has prints the string “Random Quote Module”. So we have our default view or layout written and Joomla knows to look for this file when a specific layout has not been given to it. Now we need to edit the module’s entry PHP script and let Joomla know we are using layouts. Open the mod_random_quote.php file and remove the echo statement and add the lines in red.

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

require JModuleHelper::getLayoutPath('mod_random_quote', 'default');

Joomla has an abstract class called JModuleHelper that has methods to work with modules. Most of these are used by Joomla when it is parsing and running modules, but one of them is geared to getting a specific layout for a module, getLayoutPath() and what it does is pretty straight forward, you supply it two parameters. The first is what module are you looking for and in our case it is our module, mod_random_quote. The second parameter is the layout you want, and in our case we want the default layout (the default.php file) for this module. What is returned is the path and filename of the layout (or view) we are looking for. This file is then brought in place with the PHP require statement.

In this case we are asking for the default view explicitly, but as we expand the capability of the module later, we will introduce module parameters which we will use to allow the administrator to choose from different layouts.

Finally we need to let Joomla know to copy our new files when we install the module. Open the manifest file and add the following line:

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.5" client="site" method="upgrade">

<name>MOD_RANDOM_QUOTE</name>
<author>Joe Hildreth</author>
<creationDate>05 JUL 2016</creationDate>
<copyright>(c)2016 Joe Hildreth, All rights Reserved</copyright>
<license>GNU General Public License V2 or later</license>
<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.<;/authorEmail>
<authorUrl>http://www.myheap.com</authorUrl>
<version>1.0.0</version>
<description>MOD_RANDOM_QUOTE_DESCRIPTION</description>

<files>
<folder>language</folder>
<folder>tmpl</folder>
<filename module="mod_random_quote">mod_random_quote.php</filename>
<filename>mod_random_quote.xml</filename>
<filename>index.html</filename>
</files>

</extension>

In the above code we have added another <folder> tag to let Joomla know to copy this folder and all of its contents to the module’s folder on the front end or site application of the website. Once you have added the line save and close the file.

Checking our work … again

In your project folder, delete your old archive and create a new one, being sure to include both the language and tmpl folders with the files. Go to the back end and install your module again. If you receive any error notifications when installing, double check your manifest file for errors. When you have the module installed go to the front end and see that it works. It should display the text “Random Quote Module”, which we know is coming from the default layout.

If you have any errors on the front end, check that you included the tmpl folder in your manifest and that the spelling is correct. Check the spelling of your default.php file in the tmpl directory, and finally check your call to the getLayoutPath() method that you don’t have a typo in the method name or one of it’s parameters.

Some Final Thoughts

I have talked about internationalizing the module by using language strings and the concept of different layouts or views when displaying the contents of the module. We will see both these topics come up again later as we develop this module.

In the next tutorial, we will develop the database for our module using a few tools to help us generate the SQL file that Joomla will need to install the data. I will also cover the SQL files required for installing, updating and removing a module from Joomla. I will also introduce versioning the module as it plays an important role once you start with a database.

If you have any questions, please feel free to post on my YouTube channel located at https://www.youtube.com/c/MyHeap or use the contact link on my website by going to http://www.myheap.com

END OF TUTORIAL

Creating a Site Module for Joomla 3.x - Part 2

Yes, it’s a Joomla Module, but it’s incomplete.

television icon 64x64pdf icon 64x64zip icon 64x64Now that a minimal Site Module has been created for Joomla, it is time to expand on it a bit. Recall, that we used the least amount of code possible to create and install the Module. The problem with this minimalist approach is that we left some holes that really need to be filled in. For example, the manifest file, the module’s XML file, will hold meta-data for the module that Joomla uses in the back end, or administrator application, to manage the module and provide the site administrator information about it. We also did not take into account that the web server will list the files of our module if we go to the folder directly. To see what I am talking about, open your browser and navigate to the following URL:

http://joom.dev/modules/mod_smallest

The actual URL you will enter will depend on what you called you virtual site and what you named your module. If you have been following the tutorials as I have produced them, the link above will be correct, otherwise you will need to adjust according to your environment.

The next issue, is that we did not prevent the module from running outside of Joomla’s environment. To demonstrate this, enter the following URL in your browser.

http://joom.dev/modules/mod_smallest/mod_smallest.php

You will see that the code in your module will execute. If you are following these tutorials, you will see the output of the module, “Welcome to my module!” has been printed to the screen. These two situations increase your vulnerability to a hacker out on the Internet. We should always consider that a user of our site has malicious intentions and write our code appropriately. So lets take care of these issues in this tutorial.

Exploring the Manifest file.

Recall that the manifest file we wrote for the minimal module contained the following code:

<?xml version="1.0" encoding="utf-8"?>

<extension type="module" version="3.5" client="site" method="upgrade">
<name>Smallest Module</name>

<files>
<filename module="mod_smallest">mod_smallest.php</filename>
<filename>mod_smallest.xml</filename>
</files>

</extension>

Although the above code fulfills the minimum that we need to install our module, there is more that we should add to it to make the module that we have written more meaningful to the site administrator in the back end of Joomla. Add the following code, marked in red, to your module’s manifest file.

 

<?xml version="1.0" encoding="utf-8"?>

<extension type="module" version="3.5" client="site" method="upgrade">
<name>Smallest Module</name>
<author>Joe Hildreth</author>
<creationDate>30 JUN 2016</creationDate>
<copyright>(c)2016 Joe Hildreth, All rights reserved</copyright>
<license>GNU General Public License V2 or later</license>
<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.<;/authorEmail>
<authorUrl>http://www.myheap.com</authorUrl>
<version>1.0.0</version>
<description>The minimum code example for a module.</description>

<files>
<filename module="mod_smallest">mod_smallest.php</filename>
<filename>mod_smallest.xml</filename>
</files>

</extension

 

Let’s discuss the additions and where Joomla uses them. The tags we added to the manifest file above, starting with <author> … </author> and ending with <description> … </description>, are the meta-data tags. Joomla will use the contents of these tags to populate certain items on the back end. We will start with the first tag:

<author>Joe Hildreth</author>

The <author> tag contains the name of the writer of the extension. You would put your name between these tags, or your company or whatever you want. Joomla uses this value in the Author column when you are in the back end managing the extension. Extension | Manage | Manage from the main menu in the back end of Joomla.

<creationDate>30 JUN 2016</creationDate>

The <creationDate> tag will contain the date the extension was written or released. There is not any specific format that you have to use. I could have used June 30th, 2016 or 2016-06-30 or any other format I wanted. Joomla uses the value of this field to populate the Date column in the back end when you are managing your extension.

<copyright>(c)2016 Joe Hildreth, All rights reserved</copyright>

The <copyright> tag hold the copyright information about the extension. The copyright data can be in any format you like. I am unaware where Joomla uses this data if at all. If you know, please contact me. More importantly, it lets a user of your extension know who has the copyright.

<license>GNU General Public License V2 or later</license>

The <license> tag contains the licensing that the extension was released under. This field will let the end user know how your extension and the code can be used. Many folks will find an extension that is sort of what they need and make changes to it. The license that the extension has been released under will let you know what you can and cannot do with the extension and its code. This is another that I do not know where Joomla uses this data. Again, if you know where this is used, please let me know.

<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.<;/authorEmail>

The <authorEmail> tag will contain the email address that an end user can use to contact the extension developer. Perhaps you need some support on how to use the extension. I am unaware where Joomla uses this field. Again, if you know, please let me know.

<authorUrl>http://www.myheap.com</authorUrl>

The <authorUrl> tag informs the end user the web address of the extension writer. This would be the address you would provide where they can go to get updates, instructions on use and general support. Joomla does not display this on the back end that I know of. If you know otherwise, please let me know.

<version>1.0.0</version>

The <version> tag holds the version of the extension. This value of this tag is used in the back end when you manage your extension and is used to populate the version column. Joomla also uses the value of this tag during the install if you are using the upgrade method. The version is stored in Joomla’s database and is compared to any other version stored there for the extension. We will cover this in more detail when we talk about versioning your extension.

<description>The minimum code example for a module.</description>

The <description> tag holds the description of your extension. It is used in the back end when you are managing your extension. The description is displayed when you mouse over the name of your extension as a tool tip.

That concludes the meta-data fields of the manifest file. One other thing I should point out. The <name> and <description> fields are translatable, meaning that you can use a language string as the data for the tag for internationalization of your extension. We will cover this when we get to language strings and internationalization. Now let us address our security issues.

Addressing the Security Vulnerabilities

Apache in a default configuration will list the contents of a directory if the default files cannot be found to load. Now the apache web server can be configured not to display the contents of a directory and I am sure that Microsoft’s IIS server can be too. The problem is, as an extension writer, we have no idea how the end web server will be configured so we should take the effort to prevent the directory listing ourselves. Fortunately, this is simple for us to do. We simply add an index.html file to each folder we create in our extension. So, create a new file in your module’s project directory and name it index.html and add the following code.

<!DOCTYPE html><title></title>

Save and close your index.html file. If you load this file in your browser, you get an empty screen. That will solve the problem of listing the contents of the directory. Now all we have to do is have Joomla copy this file over when we install our extension. Open your manifest file and add the line in red below:

 

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.5" client="site" method="upgrade">

<name>Smallest Module</name>
<author>Joe Hildreth</author>
<creationDate>30 JUN 2016</creationDate>
<copyright>(c)2016 Joe Hildreth, All rights reserved</copyright>
<license>GNU General Public License V2 or later</license>
<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.</authorEmail>
<authorUrl>http://www.myheap.com</authorUrl>
<version>1.0.0</version>
<description>The minimum code example for a module.</description>

<files>
<filename module="mod_smallest">mod_smallest.php</filename>
<filename>mod_smallest.xml</filename>
<filename>index.html</filename>
</files>

</extension>

Simply adding the file to the <files> section of the manifest is all Joomla needs to know that it should be copied into the site when you install your module.

That solves that problem, so now lets address the issue of a user being able to execute the code in our module outside the Joomla environment.

If you watched the video on the Joomla Execution Cycle, you learned that Joomla defined a constant in the index.php file that it loads when it starts with the line:

define('_JEXEC', 1);

We can leverage this knowledge and use it in our own scripts. If at the beginning of our script we check for this constant, we can decide what to do based on its existence. So, open your mod_smallest.php file, or whatever you named it, and add the following code marked in red:

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

echo 'Welcome to my module!';

This line of PHP simply checks to see if the constant _JEXEC has been defined and if it does not exist will kill the script. By placing this line at the top of our file, we are assured that Joomla is calling our file and not someone on the Internet. Save your file and let’s check out our module in Joomla.

Checking out our work.

Select the three files in your module project directory, index.html, mod_smallest.php and mod_smallest.xml and zip them up into an archive. With that done, log into the back end of your Joomla installation and re-install your module. There is no need to uninstall the old copy because we selected the upgrade method in the manifest, meaning that Joomla will copy over the files that were installed from the last go.

Now, let’s check our work.

Go to Extensions | Manage | Manage in the back end and find your module. Notice that the Author, Version and Date fields have been filled in with the information we supplied in the meta-data fields in the manifest file. Hover your mouse pointer over the name of your extension and notice that the description that you gave in the manifest file now appears as a tool tip along with the name of your extension. Pretty cool, huh?

Now, open your browser and point it to:

http://joom.dev/modules/mod_smallest/

Notice that apache just serves you up an empty webpage. Now, an end user has no idea what files and folders exist in our module, making it more secure than it was when we started. Enter the following URL in your browser:

http://joom.dev/modules/mod_smallest/mod_smallest.php

Notice that you get a blank screen. Since we entered the script directly, the constant _JEXEC does not exist, so the script is simply killed and there is no output. If you look at the page source you will see that it is empty.

Well we have come a long way this tutorial, but we have much more road to travel. Now that we have a firm understanding of how to write a simple Module for Joomla let’s expand our knowledge a little more. In an upcoming tutorial we will create a usable module based on what we have learned and expand on it. Thank you for participating

END OF TUTORIAL

Subcategories