10 Most Common Joomla Developer Mistakes
(and how to fix them)
Typical errors in extensions, and how to implement a fix or a workaround.
When using 3rd party extensions or even Joomla! components on your websites we often find they don't behave as expected or lack supports for standards which make their usage difficult.
Here you will find a list of the most common issues you will encounter, and pointers to quick solutions.
As a user, all that's left is contacting the customer support. But, especially in case of free extensions, this can be unavailable or untimely. Especially when the issue arises once you go live with your site and the clients are calling every 5 minutes.
As an extension developer, there are certain guidelines which should be followed but are often ignored. As a user of these components, with some php development skills, it is usually fairly easy to fix / adapt / extend these extensions to fit your needs. Without further ado let's dive into our list!
1. Missing support for custom layouts or custom classes
Usually when you develop a component or module you provide just a single view layout: default.php. Since 95% of the changes users require deal with graphics, this is the single item most users will need to change.
In order to allow users to create a new view, instead of overriding the one you provided, all you need is to add the layout parameter to the extension's configuration, and make sure its value is used when rendering the view.
Both components and modules can accept a custom css class, which - depending on your template - can be appended or joined with the standard classes. As above, the standard name is moduleclass_sfx, and this will appear in the module's or component's containers, thus allowing custom module-dependant css-styling
3. Missing / incomplete / error-prone support for cache
Joomla cache is awesome. It allows for several levels of caching and will easily take a huge load off your webserver. Joomla handles cache efficiently even if the programmer didn't implement any custom strategies; however in this case two modules on the same page, with different parameters, could end up displaying the same content because the cache doesn't take into account the module configuration.
Please see the entire article on cache for further details on how to fix it.
4. Missing translations
The best practice is to insert new strings into the translation files as you develop new functionality.
An acceptable practice is to review your code and extract the translations before any release.
Or you could find just a bunch of hardcoded texts in your code.
There are two places you can locate the translation files: under /language/en-GB or /module/mod_yourmod/language, the second being the preferred method by 1.6+ extension developers as it keeps all your extension in one place.
Additionally, you may load another extensions translation file, this is very efficient when delivering a package to keep duplication and maintenance to a minimum.
So even if you don't use english, the first step is to move all strings to en-GB.extension_name.ini assigning a constant (which hopefully starts with the extension name) i.e.
Now save and you're ready to use it: JText::_("MOD_MYMODULE_HELLO_TEXT") will return the localized text.
If you're extracting more than one line, it may be more efficient to first extract all of them, test the english file, and only then add them to the translated files.
5. Load jQuery. Again.
If you fancy smooth animations and smart interaction with the user, chances are some of your chosen extensions will invoke some version of jQuery, without giving you an option to use the one that's already in your template or other component.
Here the best solution is to insert jQuery at the template level, then remove it (manually) from each of the views.
A quick search for the string jquery.*\.js will usually find most.
A nice workaround is to use our "toomanyfiles" plugin, which will take care of jQuery for you.
6. Load many small files
The number of separate resources impacts the download time more than their weight in bytes.
Each component and module you use may load extra resources. It is indeed good practice to separate JS and CSS in their own files: this allows for a clean separation during development and testing; but in production it can lead to extreme site slugginess. One approach is to manually incorporate all resource files into one, but this makes subsequent maintenance and upgrades more difficult. Another is to compress the resources. But both can be easily achieved with our "too many files" plugin, which handles all the intricacies - like straightening relative paths in css - transparently.
Browser specific styles
It is common practice to embed browser specific files. For mainstream bad browsers (you know what I'm talking about) it may be more efficient to simply include the rules in the main stylesheet with modernizr or a similar approach.
Print resources are downloaded by the browser when you watch a page. So you're much better off including a @media print section in your stylesheet rather than separating it into another file.
A mention on sprites. Sprites are the very essence of optimization when it comes to graphics. Any icons or glyphs, borders, gradients on your site can be incorporated into one larger image; the rules in the stylesheets need to be updated to reflect this so that, by a clever use of background-position and size, they may display only the relevant part each time.
7. Reload jQuery under a different name
jQuery is a defacto standard, no-one's arguing about this. And it comes in different releases, and different flavours.
Alas, many extension developers resort to forcing a customized version of jQuery - which is custom only for the name - just to make sure their code runs with the right jQuery version.
Chances are, their code would run with any version after that. Reality is, you're downloading an extra 60kb off your site which you could have easily done without.
Fixing this is tricky: you need to ensure their code runs after you loaded your chosen jQuery version (off a CDN please!) then simply create a mock: i.e. in cometchat jQuery is served as jqcc. In jomsocial, as joms.jquery. In frontend scrollers from YTC, as ytc_query.
First of all, find where this is defined, and remove the library they are serving entirely, then replace is with
ytc_query = jQuery;
joms.jquery = jQuery;
and the like.
This is all that's needed, as all subsequent usage of these variables will automatically refer to the original jQuery, without burdening your users with an extra download
The toomanyfiles plugin automatically handles the most common cases of custom-renamed jQuery embeds.
8. Missing sprites
Sprites are images which contain the graphics for several items on your output. A good example is a toolbar, a buttonbar, or simply reminder icons you spread out through your site.
Usually it's easier to just have one image per icon, and another for its :hover effects when appropriate.
However this results in unresponsive hover mechanism (the browser needs to download the file) and many separate downloads. Keeping the downloads to a minimum can be a daunting task, but you can achieve massive advantages in speed just by grouping together all the glyphs on your site and create a single - download once and forget - graphic file, and using background css rules to display the appropriate portions on each item.
9. Wrong routing
A page's address is often composed of several items:
|option||com_content||The name of the component|
|option||com_content||The name of the component|
|task||display||The name of the function in the controller which is invoked|
|view||default||The name of the view|
|tmpl||The name of the template. Optionally can be set to "component" to only output the component, instead of the full page. This can be customized in the component.php file in the templates folder (create it if it's not there)|
|format||json, raw||This is usually added to requests for ajax responses|
It is very wrong to base the router.php strategy on the number of parameters; While this can lead to good optimizations in the path length, they are also a nightmare to maintain and debug. And they usually break when you're using Ajax calls.
Since the router.php is sometimes quite complex (a thousand lines is common) and its inner workings can be difficult to grasp with a casual look, it should always be modified with reverence.
You may invoke a hidden view by passing its name in the url, force a task, a view or a layout just on the url, hence it's important to keep in mind: if you choose to ignore view and template, just leave them out of the optimization process; then stick to a rule i.e. /task/view/id and make sure the paramter order matches across all your calls. This will make it very easy to implement and maintain.
10. Layout breaking code or styles (wrong rules)
Sometimes extension developers - even module developers - think they can get away with super generic css i.e. defining a rule for p, div or span. This usually breaks everything else on the site, but you can easily get around it by prefixing the offending rules with some container that's specific to that module (thus a small change in the css resolves the issue).
Another quite common issue is missing divs (which break layout!). You can find out about such errors by validating your pages. Finding the offending piece of code can be tricky, just try to unpublish modules one by one as you refresh the page and find the offender.
11. Missing input validation
Even if you perform some browser-side validation, all parameters must be filtered. Use the appropriate JRequest::get* classes, in particulare getVar() can have a second param to set the limits i.e. cmd, script, raw, etc.
One thing you must _always_ escape is variables that go into sql statements or end up in the filesystem: these are the two most common chances for attack, and while not compromising the components' functionality, they pose a major threat to your website's security. So head on to joomlaextensionsblacklist.com and make sure the extensions you are using are not suffering from these vulnerabilities. Follow your fellow extension developers on twitter / feed / mailing list to make sure you are notified of new versions.
12. Worst practices
- The extension's css features !important or browser-specific rules
- The view queries the db (i.e. you see a SELECT sql statement in a view or even worse in a layout)
- The controller or models output html (except for html helpers)
... the list is long. Beside the obvious stylistic issues, it really doesn't pose a major threat to your site