0. go through basic Joomla! documentation
Joomla! Beginners guide: [http://docs.joomla.org/Beginners]
Joomla developer network: [http://developer.joomla.org/]
which includes very useful Joomla framework API: [http://api.joomla.org/]
Joomla! forum: [http://forum.joomla.org]
1. project structure
It is useful during development to keep the code in only one place. You can easy use this structure with your IDEs [http://en.wikipedia.org/wiki/Integrated_development_environment] and VCS [http://en.wikipedia.org/wiki/Version_control_system]
It is recommended to use next structure:
project-root com_component site ... lang ... en-GB.com_component.ini de-DE.com_component.ini component.php admin ... lang ... en-GB.com_component.ini de-DE.com_component.ini admin.component.php install.sql uninstall.sql component.xml mod_module ... lang ... en-GB.mod_module.ini de-DE.mod_module.ini module.php module.xml plg_plugin ... lang ... en-GB.plg_group_plugin.ini de-DE.plg_group_plugin.ini plugin.php plugin.xml tpl_temlate template.xml ...
After creation of project structure prepare installation packages with help of Joomla! tutorials and install them to Joomla!. We will work with local installation (or dedicated server in your LAN) because another variants decries performance of developers.
After extensions installation process change files of extensions installed to Joomla! with GNU/Linux symbolic links [http://en.wikipedia.org/wiki/Symbolic_link] or Windows Vista symbolic links [http://en.wikipedia.org/wiki/NTFS_symbolic_link] of your project files.
Note: Don’t forget to use option “Options +FollowSymLinks” for Apache web-server for directory where your Joomla! installed to use symbolic links.
In Joomla! filenames of extensions has special structure. In mentioned structure names of corresponding extensions in filenames and directories replaced with words component, module, and plug-in. The word group in files of plugin replaces name of group to which plug-in relate to [content, editors, search, system, user].
Every group defines set of events on which plug-in will be triggered.
Ready to use project has following structure of relations: (<== symbol means symbolic link)
PRJ-ROOT/COM_COMPONENT/SITE <== J_ROOT/COMPONENTS/COM_COMPONET PRJ-ROOT/COM_COMPONENT/SITE/LANG/en-GB.com_component.ini <== J_ROOT/LANGUAGE/en-GB/en-GB.com_component.ini PRJ-ROOT/COM_COMPONENT/SITE/LANG/de-DE.com_component.ini <== J_ROOT/LANGUAGE/de-DE/de-DE.com_component.ini PRJ-ROOT/COM_COMPONENT/ADMIN <== J_ROOT/ADMINISTRATOR/COMPONENTS/COM_COMPONET PRJ-ROOT/COM_COMPONENT/ADMIN/LANG/en-GB.com_component.ini <== J_ROOT/ADMINISTRATOR/LANGUAGE/en-GB/en-GB.com_component.ini PRJ-ROOT/COM_COMPONENT/ADMIN/LANG/de-DE.com_component.ini <== J_ROOT/ADMINISTRATOR/LANGUAGE/de-DE/de-DE.com_component.ini PRJ-ROOT/MOD_MODULE <== J_ROOT/MODULES/MOD_MODULE PRJ-ROOT/MOD_MODULE/LANG/en-GB.mod_module.ini <== J_ROOT/LANGUAGE/en-GB/en-GB.mod_module.ini PRJ-ROOT/MOD_MODULE/LANG/de-DE.mod_module.ini <== J_ROOT/LANGUAGE/de-DE/de-DE.mod_module.ini PRJ-ROOT/PLG_PLUGIN/plugin.php <== J_ROOT/PLUGINS/GROUP/plugin.php PRJ-ROOT/PLG_PLUGIN/LANG/en-GB.plg_group_plugin.ini <== J_ROOT/ADMINISTRATOR/LANGUAGE/en-GB/en-GB.plg_group_plugin.ini PRJ-ROOT/PLG_PLUGIN/LANG/de-DE.plg_group_plugin.ini <== J_ROOT/ADMINISTRATOR/LANGUAGE/de-DE/de-DE.plg_group_plugin.ini
As you see languages files of plug-ins installed to administration part of Joomla!. Why so, ask Joomla! developers.
2. internationalization (i18n)
Most of extensions require internationalization. This mechanism is simple to use in Joomla!, but it has some ambiguous decisions.
To use internationalization support of text messages in the code of extensions instead of output of simple strings we should use next construction: JText::_(‘text message’); This call check current locale and using appropriate localization file returns required string.
For instance if current locale is ‘en-GB’ then it seek for appropriate file:
for “site part” of Joomla!: joomla-root/language/en-GB/en-GB.com_component.ini
and in that file I look for sting with id ‘TEXT MESSAGE’
If it can’t find appropriate file then it returns passed string.
Structure of localization file:
identifier=value
identifier – is a string, it should be written in UPPER CASE.
Value – is a localized value.
Example:
We need to output 2 internationalized strings
echo JText::_(‘This is test message.’);
echo JText::_(‘Hello world.’);
Then we create localization file for appropriate locale en-EN.com_component.ini:
THIS IS TEST MESSAGE=This is test message.
HELLO WORLD.=Hello all.
de-DE.com_component.ini:
THIS IS TEST MESSAGE=Das ist testen Meldung.
HELLO WORLD.=Halo eine Welt.
I want to note that in order to use that mechanism for plug-ins you should invoke method loadLanguage of class Jplugin:
loadLanguage(
[name of localization file],
[path to root directory of site part of admin part of Joomla!]
name of localization file, by default plg_group_plugin.ini path to root directory, can be: “j_root/administrator” or “j_root” (by default)
3. layouts
Layouts is a handy mechanism which let us to avoid using of “if construction” in “view” of the MVC model [http://en.wikipedia.org/wiki/Model-view-controller] which Joomla! 1.5 began to use actively for extensions development.
By default structure of extensions presentation in Joomla (for modules, and components) has next structure:
EXTENSION-ROOT VIEWS VIEW TMPL default.php view.html.php
Here “view.html.php” file is a common part of presentation which can commonly contains invocations of “model” (MVC) or in other words where we extract data that necessary for data output, and some simple logic.
There is a rule to place mature logic to model or controller(MVC). In the “TMPL” directory we keep different presentations. They contain markup or in other words exact presentation of data. An file “default.php “ is a default layout, so it will be used if we wasn’t selected another one. You can easily create additional layouts adding them to ‘TMPL’ directory files with name “layoutname.php”. In order to select specific layout you should in the controller(MVC) before invocation of display() function
select its name with command: JRequest::setVar(‘layout’, ‘layoutname’);
4. using of AJAX
It is hardy to imagine an application that can be developed nowadays without AJAX. [http://en.wikipedia.org/wiki/Ajax_%28programming%29]
It is much easier to use some javascript library like jquery, mootols, dojo, etc.. to invoke Ajax-based methods. I like jquery [http://jquery.com]. However Joomla! Developers have selected another Javascript library – mootols [http://mootools.net] and so I earnestly recommend to you to use for ajax methods invocations Mootools library. If you anyway want to use your favorite JavaScript library you must switch your library to the compatibility mode.
For instance for Jquery it can be do it with:
var jq = jQuery.noConflict();
then instead of ‘$’ you should use ‘jq’ but anyway keep in mind that most of extensions for JavaScript libraries don’t use that mode and so you will have Javascript error because of name collisions.
Example of MVC flow using Ajax invocation:
- Create task in the controller, ex.: getAjaxData
“controller.php”: function getAjaxData() { JRequest::setVar('view', 'viewname'); JRequest::setVar('layout', 'ajaxlayout'); parent::display(); }
- Create layout, ex: ajaxlayout
“viewname/tmpl/ajaxlayout.php”: <?php defined('_JEXEC') or die('Restricted access'); global $mainframe; echo <ajax data>; $mainframe->close(); ?>
Important note:
You should add invocation: $mainframe->close();
in order to create output flow or it will add Joomla! standard page after result of you Ajax method. Thus creating concrete layout you can pass any data, don’t forget to setup appropriate header. For XML [http://en.wikipedia.org/wiki/Xml] it can be: header(“Content-type: text/xml;charset=utf-8″);
On client-side yous should make invoke defined method using Ajax call, using URL like:
JURI::root().’index.php?option=com_component&task=getajaxdata’;
5. mapping of tables to the Database
Joomla! using simple ORM system [http://en.wikipedia.org/wiki/Object-relational_mapping].
In order to use this mechanism you should describe your DB structure with sets of objects that inherit JTable.
For example:
foo.php:
<?php defined('_JEXEC') or die('Restricted access'); class TableFoo extends JTable { var $id = null; var $bar = null; function TableFoo(& $db) { parent::__construct('#__foo', 'id', $db); } function bind( $from, $ignore=array() ) { $from['bar'] = strtoupper($from['bar']); return parent::bind($from, $ignore); } function check() { if (empty($this->bar)) { $this->setError( 'Error message'); return false; } return true; } function delete( $oid=null ) { $res = parent::delete($oid); // here if you need you can define mechanism // to delete linked tables return $res; } } ?>
First of all it is necessary to define public variables that corresponding to fields names of table. Then you should pass name of the table and name of primary key to the constructor.
key methods:
Bind() method using in order to transfer data from external sources (ex.: requst) into object. Overriding that method you can execute specific data transformations of data before adding to the fields of the object.
Check() method make checking of data in the fields, for example it can check that fields not empty or filled with required range of values, etc.
Delete() method can add specific behavior during deletion of records. For example deleting of linked records.
Also JTable class contains set of other handy methods overriding which you can add appropriate specific behavior.
See Joomla! documentation for details.
possible use:
You can get object in the model (MVC) with following: $row =& $this->getTable(‘foo’);
to delete record you invoke: $row->delete($id)
to store record to db:
$row->bind($data);
$row->check();
$row->store();
If then you need get value of primary key you can simply take the value from the object: $row->id;
Surely it is better to add to described calls check of result of methods executions.
Tags: joomla, joomla development
Hi! I translated this article to russian and posted in my blog, here:
http://bolzamo.org.ru/154/
Thanks for sharing your tips and hints. The one on internationalization and ajax was very informative.
Only want to say your article is brilliant. The clearness in your post is simply spectacular and i can take for granted you are an expert on this field. Well with your permission allow me to grab your rss feed to keep up to date with future post. Thanks a million and please keep up the good work.
I like your website.. It had some greatinformation I am excited to see the next update.
Joomla is definitely the best CMS ever
Hi there.
Great site for some quick hints on developing for Joomla.
I am curious though. I am trying to internationalize my javascripts, without adding extra javascript declarations, eg I would like to avoid using javascript for internationalizing labels.
This is what I would like to avoid:
$doc = JFactory::getDocument();
$doc->addScriptDeclaration(‘window.mymodname = {
label1: “‘.JText::_(‘MOD_MYMODNAME_LABEL1′).’”,
label2: “‘.JText::_(‘MOD_MYMODNAME_LABEL2′).’”
};’);
I want to be able to use my Jtext in my javascripts plain and simple, but it seems Joomla won’t let me.
I’m guessing Joomla won’t parse javascriptfiles, hence the Jtext won’t be read.
Maybe I´m going about it the wrong way, maybe I should be looking at the construction of the javascript instead?
Cheers
to Amrit.
Unfortunately there is good way currently to make it.
You have to use different workarounds.
For example you can add additional function to controller:
function some_function() {
header(‘Content-Type: text/javascript; charset=utf-8′);
require_once(‘PATH_TO_YOUR_JS’);
die();
}
And then add it to your page:
$variable = JFactory::getDocument();
$variable->addScript(JRoute::_(‘index.php?option=com_SOME_COM_OBJECT&task=some_function’, false));
Excellent post. I used to be checking constantly this weblog and I am impressed! Very helpful information specifically the final section
I handle such info a lot. I was seeking this certain info for a long time. Thank you and best of luck.