joomla extensions development best practic - francesco abeni

26
Best practices for Joomla extensions developers A collection of basic tips for anyone who writes Joomla extensions (or plans to do it shortly) Written by Francesco Abeni Published by GiBiLogic (https://extensions.gibilogic.com) 1

Upload: gunjan-pandya

Post on 20-Nov-2015

225 views

Category:

Documents


4 download

DESCRIPTION

basic extension development

TRANSCRIPT

  • Best practices for Joomla extensionsdevelopers

    A collection of basic tips for anyone who writes Joomla extensions (or plans to do it shortly) Written by Francesco Abeni Published by GiBiLogic (https://extensions.gibilogic.com)

    1

  • A call to actionJoomla developers: the time has come for a global quality improvement of the Joomla extensions code. So, if you

    develop extensions (or you're thinking about doing it) please read on. All the world will be grateful sooner or later. In this long book, you will learn a lots of basic tips about how to get the most out of your development time: I will

    tell you about all the good practices that I've come to learn by myself or picking from fellow Joomla devs. Thosepractices will speed up your coding and/or let you produce a better result, so you win in any case.

    A disclaimer. Coding is the art of solving problems by creative thinking, and if you cannot do that, I cannot teachyou anything. In other words, this article is for developers. If you have never coded in your life, you should read otherbooks / articles first.

    And another disclaimer: most of these best practices are written and tested on Joomla 2.5, which is still where I domost of my development work. There are a few slight changes for Joomla 3.x and this book will be updated in the nearfuture to reflect them.

    This book is organized as a series of steps, from the most basic (get a decent editor) to the most complex (do realobject-oriented programming, please). At each step you will find links to look for if something is not clear. So the paceat which you will read the article will be determined by your own level of knowledge. Experienced developers will gothrough it in a breeze, picking some suggestions here and there. Beginners may have to stop more frequently to learnsomething more about the tools / techniques referenced in the article.

    FeedbackIn any place, if you find mistakes or if you disagree with my suggestions, please let me know. You can contact me:

    via e-mail at [email protected] via Twitter at @f_abeni

    I will be happy to receive any kind of feedback and discuss it with you, so that future versions of this book may beupdated if I feel I have learned something new.

    2

  • What is all this about?My resolution to write about best practices comes, to be honest, from outside the Joomla world.Lately I have taken the habit to attend conferences about technologies that I don't know anything about. Since it's all

    new to me, it's usually a very difficult and tiring conference, but I end up knowing at least a bit of a new technology,and that's a good thing. And on top of that, at conferences I usually meet some of the best developers out there, so I amalways due to learn something.

    By attending some of this conferences, which were about non-Joomla PHP frameworks, I had a glimpse of howwell organized such frameworks are, and about how a good developer can:

    gain a lot of time create software that works better and faster create software that is ridiculously easy to fix and improve create software that is easy for anyone else to understand and work on

    Writing an extension for Joomla is somewhat easier than to write an application for another framework. That may bea good thing because it lowers the entry barrier, but it's also a bad thing because of exactly the same reason. How manyof you have written an extension by basically just copying and editing an existing one?

    Just when I was thinking about this topic to decide if it was worth some additional time, I read a tweet from ourfriend and Joomla contributor Janich Rasmussen:

    Reviewing exts = really ashamed of all those fellow devs who ignore true framework and cms usage! :( As soon as I understood that I wasn't alone, it was clear that the time was right, and that something should have

    been done about all this. I started writing a series of blog posts on our own Joomla extensions site(https://extensions.gibilogic.com/blog.html), and after a while, I took all those articles an put them together, with a bit ofeditorial work to get a better and more coherent work. What follows is the result of that.

    3

  • SummaryAs I mentioned before, we're going through a series of well defined steps, starting from the basics. You may have

    already dealt with some of the proposed topics, and have nothing more to learn: in that case you can just skip that stepor possibly read it very quickly just to confirm you're not missing anything.

    Here's the topics we're going to talk about:

    PART 1: prepare your environmentuse a good IDEuse a good versioning tooluse standardslearn

    PART 2: everything in its right placethe filescss and javascript for your extensionthe joomla framework

    PART 3: MVCwhat MVC is really aboutMVC sample codeother useful files in your MVC component

    PART 4: other tipsbasic error managementnaming conventionscommentsdocumentationsmaller extensionsshared librariesabout version numbers

    Conclusions

    4

  • PART 1: prepare your environmentBefore talking about the code itself, let's focus on the tools and the attitude you need if you aim to produce better

    code.

    Use a good IDEAn IDE (Integrated Development Environment) is the software program you use to write your code. A good IDE can make an incredible difference in the quality of your code and the time you spend doing it. At the very least, an IDE should give you the following features:

    edit more than one file at once syntax highlighting, so it's easier to spot typos quick visual index of classes, methods and variables autocomplete of brackets / quotes / tags and language keywords autoformat of your code according to a given set of standards a real-time compiler that alerts you about syntax errors

    This is just a very basic list, and if your current tool doesn't support at least the listed features, you really shouldconsider getting a different editor and learning how to get the most out of it.

    A professional IDE can offer much more than this, for example:

    integration with a versioning tool (more about that shortly) integration with phpUnit testing tool ability to extract phpDoc comments integration with FTP

    The idea is that once you fire up your IDE, you do everything you need from there and you don't need to switchback and forth to any other application.

    Take your time to learn all the features of your current IDE. It may already have many additional features to speedup your development, that you are not using just because you don't know they are there.

    I currently use NetBeans (https://netbeans.org), after a long spell with Geany, while in the past we had experienceswith PsPad. I also heard good reports about PHPstorm and of course Eclipse. But that's not really important, use whatyou like as long as it helps you code better and faster.

    Use a good versioning toolIf you don't know what a versioning tool is, stop coding right now and don't restart until you know and use one. I

    know that may sound a little harsh, but the simple truth is that versioning is one of those things that, when you startusing, makes you wonder how could you ever work without it.

    With a versioning tool you can:

    keep a clear, organized record of all your changes quickly move backward and forward between all those changes to produce different releasescode different versions without them interfering with each othereasily merge changes at any timeeasily cooperate with any other developer on the same project

    At the moment, I can't suggest anything better than Git. I come from Subversion, which is also a good tool, but Git

    5

  • wins hands down for the development style needed when working on a Joomla extension. Git it's incredibly easy: you can install a Git client like SmartGit or TortoiseGit or even the command line (if you're

    comfortable with it) and be up and running in no time. At the same time, it will become incredibly powerful once youget comfortable with it.

    If you use Git you will surely want to have a look at GitHub (github.com), an online service which lets you createremote, web-based Git repositories. It's free up to 5 repos and they have commercial plans for more repos andadvanced features. GitHub is really handy if you want to:

    share your work and accept contributionscooperate from the start with other developershave a central repo so you can work from different workstationshave a backup copy of your work

    Nowadays many Joomla related projects, and the Joomla core code itself, are hosted on GitHub. The interestingthing is that you can comment and follow other developers work, so it all makes for a more social coding.

    If you like to read a good book about it, look at the free Pro Git Book (http://git-scm.com/book) written by one ofGitHub co-founders.

    Use standardsYou're not alone, even when you think you are: your code may be read by others for several reasons. They may

    want to change something for their own needs, or change something and contribute back, or just want to evaluate howgood you are as a developer. By making your code easier to read, you are making the life of these people easier, andthey will be grateful.

    Also, don't forget that there is always at least one other person: it's yourself, two years in the future, that will swearback at you because he/she is having a hard time fixing a bug or implementing a new feature and cannot understandwhat the hell did you meant when you write that piece of ugly and unreadable code.

    So the golden rule here is: use a standard whatever it is. We'll come back later to naming conventions,indentations, and so on, and give you some suggestions, but the basic line is: choose one standard, possibly from theJoomla guidelines (http://developer.joomla.org/5-policies/3-Joomla-Coding-Standards.html), and stick to it for all yourprojects. You will make a lot of people happier, including yourself.

    LearnAll topics mentioned so far are one-time tasks: you choose a good IDE and a good versioning tool, and you're done;

    you set a standard and start to use it, and won't ever come back to it. But there is a task which never ends, and it'slearning.

    There are lots of places: you can attend conferences, browse forums, read books, watch videos, or - even better -look at the code from other extensions. A good developer always tries to improve!

    You should be able to look back at what you did just one year ago and think how much better is your code now.That is a good sign.

    Joomla and Joomla extensions are moving forward all the time. You should be prepared to keep a steadyimprovement pace, or your work will be obsolete very soon.

    That is not so difficult as it sound: mainly it's about accepting that you'll have to change and learn new things. Onceyou've entered into the right attitude, it will come quite natural.

    6

  • Part 2: everything in its right placeEach component is made at the very least of some PHP file to build the MVC design pattern, but on top of that you

    may need some more: SQL, CSS, JavaScript, images. In this section you will learn what files to use and where to place them, and also what not to use.

    The MVC filesIf you want your component to work with Joomla and respect the MVC pattern (more about that later) there are a

    few base PHP files and folders that need to exist. This is the standard structure for your component:

    componentname.php (the entry point) in the main folder componentname.xml (the manifest file) in the main folder controllers, models and views folders that holds the relevant files

    If you never wrote an MVC component for Joomla and you have no clue about which files go into those folders,you should better take a look at some tutorial like this one http://docs.joomla.org/Developing_a_Model-View-Controller_Component/2.5/Introduction and then come back to this book.

    Related to other ways to write an MVC component, the only significant difference here is that we don't have a maincontroller.php file; we invoke a single controller directly from the entry point, according to the requested object.

    Additional backend files and foldersDo you use table classes? You really should. In that case you will have an additional tables folders for such files. And it's a good idea to keep a separate sql folder where you can put your install / uninstall / update SQL files. Finally, you may have to use helpers: as you may have guessed by now, their perfect place is an helpers subfolder

    in the root of your component. Later on in this book I'll come back to what are all these files and how you should use them; currently just take note

    of the additional folders I mentioned, so you know where to put them.

    AssetsAssets are all those additional static files that your component may need. The most common types of assets are

    stylesheets, javascripts, and images. I've seen them put in so many different places that it made my eyes fill with tears.

    First of all, don't put them all in one single folder but separate them in three folders called css, img a n d jsrespectively. These names are short and easily recognizable, and they've become a widely used standard so it's a goodchoice: forget any other names like styles, scripts, images, and so on.

    After that, you have to decide where to put those folders. You have two acceptable options:

    an assets folder in the frontend of your componentFor example, /components/com_componentname/assets/. Please note that I said "in the frontend". We stronglysuggest to have all assets in the frontend, even when you use them in the backend pages.

    a com_componentname (or mod_modulename, and so on) folder in the media main folderFor example, /media/com_componentname.

    The second option (using the media folder) is definitely my preferred way to handle it; that way, all medias for allextensions are easy to find and located in a single place.

    You may also decide to have a set of assets shared between several extensions; in that I would still suggest to put itin the media folder with a common name, for example /media/gibilogic/.

    Images

    7

  • But wait... we already talked about images, didn't we? Almost.You can have two types of images in your component:

    the assets images are the icons, logos, and so on that are part your extension layout the data images are images that are part of your extension data, possibly uploaded by the user

    For example, the cart icon in an e-commerce component is an asset, while the image for a certain product is a dataimage.

    The place for assets has been discussed in the previous section. The place for the data should be acom_componentname folder in the images main folder: /images/com_componentname/. You may also have additionalsubfolders if you have different images objects; for example, products images will be in/images/com_componentname/products/ while categories images will be in /images/com_componentname/categories/.

    CSS and JavaScript for your extensionsSince the Joomla CMS already provides many excellent CSS and JS libraries, you should try very hard to avoid

    loading additional libraries and use as little custom CSS and JS as possible. Especially in Joomla 3.x, you have thechoice between:

    the MooTools JS library: it was the only one included in J1.5, I like it very much, but it's probably going tobe removed in future versions of Joomla

    the JQuery JS library: it is slowly become the standard library and it's probably the safest choice from nowon

    the Bootstrap CSS / JS library: it brings a little revolution in the web design and Joomla 3.x strongly relies onit even for core components

    All these libraries means that you have a lot of styles, effects and interactions available just by loading them andusing the correct HTML elements and classes in your extension. Yes, I repeat: you can use CSS styles and JavaScripteffects without having to write a single CSS / JS line.

    If you leverage this, you can focus on the core logic of your extension (PHP/HTML) and your extension style andbehaviour will automatically adapt to the Joomla site it's on.

    Of course you need to include these libraries by using the correct Joomla commands, so to avoid loading them morethan once. By the way, if you find yourself stuck with a conflict between different libraries or different versions of thesame library, the excellent JQueryEasy plugin will help you make some order out of the mess(http://extensions.joomla.org/extensions/core-enhancements/performance/jquery-scripts/18327).

    All of that said, if you really must use some custom CSS / JS, read on for some advice.

    External stylesheetsWhen coding the layouts of your component, you should not have any kind of style information mixed in your

    HTML code: put it in external CSS files instead. In the layout, use HTML classes and ids, and let the CSS stylesheets doall the rest. This is true even for small, innocent styles like

    Anyone who's using your extension should not be forced to do a template override just because you put some inlinestyle which is breaking the overall layout. For web designers and integrators, applying an additional CSS rule to changethe style is way easier than write a template override of the whole layout.

    This kind of development also comes handy if you want to provide some kind of theming framework for yourextensions, i.e. provide different skins for your extension. It's much easier to provide a different set of CSS files insteadof different PHP files, so when you change the logic of your component you don't need to modify different files.

    So: no inline styles in your HTML, all styles go in a different stylesheet file.

    8

  • Unobtrusive JavaScriptSince JavaScript entered the web many years ago, we've all got used to seeing it used inline with additional tag

    attributes like onclick, onsubmit, and so on. But what we said about CSS stands true for JavaScript as well: that is hard to change and require a template override

    even for very small changes. The best way to go is to use unobtrusive JavaScript.To simplify as much as possible, the term unobtrusive JavaScript refers to the good practice of applying such

    events at at runtime by using the document.onload command. An example will make it very clear. Instead of writing:

    and then assign the event at runtime, as below (this is a sample in jQuery style, but you can do that with manydifferent libraries and even with JavaScript core commands):

    jQuery(document).ready(function($){ $('submit').click(function(){ validateForm(); });});

    If you're not comfortable with jQuery, the above code basically listens for the document (the whole page) to be

    ready; when that happens, a listener is attached to the HTML element with id "submit", so that some other JavaScriptcode will be run when that element is clicked.

    For a very simple example like this, of course, the new code seems uselessly bigger and more complex than theoriginal one. One can wonder what's the good in that. But:

    keeping all the JavaScript logic in one place simplify the debug (especially for other people)it is much easier for other to change that behaviour with some additional JavaScript, without changing the

    original fileas soon as your JavaScript does slightly more than that, you will see that being able to attach / detach / fire

    JavaScript events without the need to modify your HTML code is a big bonus.

    Of course, all the JavaScript code should be placed in a separate JS file and not just above the HTML code in yourlayout.

    Joomla frameworkIn this context, a framework is intended as a set of libraries and classes that take care of common tasks, so you don't

    have to rewrite them from scratch. If you're an extension developer, you will surely have heard about the Joomla framework. This is an intermediate

    layer between the PHP native code and your application, that gives you several advantages:

    you have to write less code to do the same tasks you may write simpler code, because the framework handles most of the complexity you can also have extended options in comparison to core PHP methods / classes

    As a very simple example, I guess all of you use the JDatabase class: this Joomla class makes it very easy to access

    9

  • any table in your Joomla db to get and write data. There are many JDatabase methods and that offers you a lot offlexibility and security (for example the Quote and nameQuote methods) without the need for you to take care of it.

    Much in the same way, there are many other classes that can help you deal with things in such a simple,straightforward way. Just to mention a few:

    JFactory is a factory class to access most objects in the framework JApplication read and controls the whole Joomla application (either frontend or backend) JUser access the current user or any other existing user and get any related information; it can also help you

    create / modify a user from your code JSession quickly get and set session data JDocument is a very neat tool to deal with your page, e.g. to add stylesheets and scripts to the head of the

    page JHtml offers many methods to quickly build HTML elements JLog makes your debugging much easier because you can write down what's happening JFilterInput analyze and sanitize your input JDate is very helpful in handling dates and timezones JFolder and JFile can access and check your filesystem objectsJUri deals with URLs and current site informationJVersion gets info about the current Joomla version

    There are even more, this is just a short list of the most commonly used.By using these classes you can get info or run a task with a couple of lines of code. If you don't use them, you are

    wasting in your time in writing code that's already there, usually better and safer than yours because it's been reviewedby many and fixed along the way.

    A little drawback hereUsing a framework has always a little drawback: if it changes, you have to change your code to adapt it. In theory,

    that should not be a framework-specific problem because the same thing happens with PHP core commands. But whilePHP changes very slowly and keeps backward compatibility usually for a very long time, the overlaying frameworkchange faster. And the Joomla framework is especially quick because it follows the evolution of the Joomla CMS,which is the main application built on top of it and basically what we all know as Joomla. This fast changing speedhas sometimes raised complaints amongst Joomla extension developers.

    But we're still talking about changes that are introduced at least one year in advance, so if you keep informed aboutwhat's happening, you should not have any issue. If you balance this with the time you save while coding, plus theshortness and clarity of your code that the Joomla framework allows, you will surely conclude that it's still largelyworth it.

    If you're in the middle of a framework change (e.g. from J1.5 to J.2.5) and you want your code to be compatiblewith both versions, you may be forced to use a different code according to the framework version. What I do andsuggest is to keep a single package: you can check Joomla version with JVersion class, and do different tasksaccording to the retrieved information.

    PHP classes and advanced featuresOk, now you're determined to use the Joomla framework classes whenever you can, but don't forget that you're still

    coding in PHP. There are many useful classes and features already present in PHP core, not to mention what you canadd by means of PEAR and composer. As a very meaningful example, the DateTime and DateTimeZone classes arevery useful and - combined with the Joomla JDate class - will give you all the power you need to convert dates, addthem, subtract them, and so on.

    At each PHP releases, new features are added that can shorten your code, so be sure to keep up to date with latestchanges. And since we're talking about PHP releases, do you know that:

    10

  • PHP 5.2 has reached its end of life 16. Dec 2010 PHP 5.3 has reached its end of life 11. Jul 2013PHP 5.4 has been released 1. Mar 2012 PHP 5.5 has been released 20. Jun 2013

    Each new version brings new features and significant performance improvement, so you should always encourageyourself, your colleague and customers to keep their hosts updated to later PHP releases.

    Keeping a little backward-compatibility with previous versions of PHP it's not difficult since, as we stated before,PHP changes quite slowly - but should not become your main focus. Try to code for current stable release, and use thenew features when you can.

    11

  • Part 3. MVCWhat MVC is really about

    A few pages ago I suggested you to check a tutorial about creating an MVC component(http://docs.joomla.org/Developing_a_Model-View-Controller_Component/2.5/Introduction) . I hope you read it oranyway that you are able to create at least a very basic component with a Model, a Viev and a Controller. If you do,you are using MVC (Model - View - Controller) design pattern as any decent Joomla component does.

    Basically, a design pattern is a standard way to structure your code; but that is only the beginning.

    Object-oriented programmingOn top of the suggested tutorial, you may find many others about building a Joomla component. Also some books

    have been written about that topic. Some of them are quite good in explaining the relationships between models, viewsand controllers, my favourite being the one by Joseph Le Blanc that uses an interesting analogy with restaurants.

    But now that I have learned a lot more event from outside Joomla I can defnitely say that none of those tutorialsand books put enough attention on an important fact: MVC is based on object-oriented programming, and if you wantto use it effectively you should be thinking carefully about your objects.

    Models, views and controllers are not independent. Usually they go in triplets: you have one model, one view andone controller strictly related to each other. In your component, several of these MVC triplets may exist; but each oneof them should handle a specific object.

    If in your component you have MVC triplets named like "list", "update", "editsite", "search", you are definitely onthe wrong path and you should read carefully the next section.

    What is an object?An object is... well, a thing: a resource, something. Definitely not an action. So if your site is about books, you'll

    have to think about objects like book, author, editor. For each object you may have a display task (single or list) asearch task, an add and/or edit task, and so on. As I said just a little while ago, each object will have its own MVCtriplet: its controller, its model and its view. There are exceptions to this, but they are... well, exceptions :-).

    Please note the important difference: book is a decent object, editbook is not. Don't mix objects with tasks. Youdon't have to create a new MVC triplet for any new page you need on your site.

    For example, if you want your component to display a new page with the 10 most sold books, you should not createa votedbooks MVC, but add a new task and layout to your existing book MVC object.

    Now that we have cleared the air a bit about objects, let's focus on how the MVC should really work.

    DispatcherIn the overview of the component structure (part 2) I said there is no global controller and that each object has its

    own controller. But we still need to choose what object has been requested, so that we can call the appropriatecontroller. This part of code is called dispatcher and in my component it's usually included in the entry point(componentname.php).

    ControllerThe controller is often under-rated, while it's probably the most important part of your component. Here the most

    important decisions and actions happen. Amongst other things, the controller:

    filters the inputdecides what task has been called and if it's a valid taskchecks if the user is allowed to do thatoptionally, calls the model to do some process or get some dataswitches the control to the relevant view

    12

  • Too many times, while looking at some extension code, I have seen only very basic code in the controller, while thecorresponding model and view are overstuffed with auth checks and processing logic. By moving more code into thecontroller, which is the first step in the process, you will make yourself a big favour because your processing logic willrun early and will not be mixed up with data access and display stuff.

    The modelThe model is a very focused character. You may think of it as a librarian. It is not usually concerned with the overall

    picture: he just gets the requested data and returns it. It relies on the controller to know what data should be taken and ifthe user is allowed to get such data, so it just goes on with it and returns the requested data.

    You can correctly deduce that the model is the place for the queries: in fact, all the SQL in your components shouldbe in your models, and nowhere else.

    The viewThe view should take care of the display part, so it should not have any input processing or sql query. Compared

    with other frameworks, in Joomla the view is a bit more powerful, and takes care of some tasks that should really behandled by the controller. For example, in Joomla the view iself calls the model to get the data; in other framework, thecontroller does that and passed data to the view, which just shows them. Anyway, this is how it works with Joomla solet's stick with it.

    It's important to understand that a single view can handle different types of page, by a combination of differentmethods and different layouts (the files in the tmpl subfolder). In a single view class you may have for example adisplayItem and displayList methods, that request different data and load different layouts.

    MVC sample codeTime to put all this into practice and to see some code. To make it easy to follow, this is a very basic sample

    component that, as you may have guessed, will manage books.The following sample code has been written with particular attention to make it readable on this book, so I made all

    lines of code as short as possible. I usually don't put so many newlines; that is not my standard, so to say.

    Entry pointIn a simple component, the entry point does not usually do very much. Let's see a full, albeit very simple, entry

    point.Listing 1: component entry point

  • I left the initial header comment on purpose: i suggest to always include some meta info about the file. I use andrecommend to use the standard PHPDoc format, which you can then parse with existing tools.

    Browsing the code you can see that, after the basic _JEXEC check, the code:

    includes the base controller class gets view and task info from the request and convert them into a full task in the format object.task loads the relevant controller, executes the task and redirects to the final page.

    An important note here. Using the view parameter to define which object we want is a common convention inJoomla components, but we may have passed a controller parameter instead, or just a full task in the object.taskformat. That convention is a reminiscence of the single controller way, which I don't use anyway. In fact, we are notcalling directly any view: we use that parameter just to know which controller to pass the control to, or in other wordsto do the dispatching.

    If your component grows complex, you may have here in the entry point some additional initialization code, forexample you may want to include additional JS / CSS libraries or just common classes you have developed for yourcomponent. For a simple component, though, the above code will be enough.

    The controllerIn the following code you may see a sample controller; you will have a controller for each object that your

    component handles. This time I removed the initial header comment to keep the code listing short, but I left somecomments above each method to show you additional PHPDoc keywords.

    Listing 2: book controller

  • $this->getModel( 'Editor', 'MyBooksModel' ), false ); } public function display() { $this->view->display(); } public function index() { $this->view->setLayout('index'); $this->view->display(); } public function edit() { $this->view->setLayout('edit') $this->view->display(); } public function add() { $this->view->setLayout('edit') $this->view->display(); } public function save() { $data = JFactory::getApplication()->input ->get('jform', null); $url = JRoute::_( 'index.php?option=com_mybooks&view=book' ); if (!$data || !$this->model->validate($data)) { $this->setRedirect( $url, 'Invalid data!', 'error' ); return false; } if (!$this->model->save($data)) { $this->setRedirect( $url, 'Error while saving!, 'error' ); return false; } $this->setRedirect($url, 'Saved ok!'); } private function getModel($name = 'Book', $prefix = 'MyBooksModel', $config = array()) { return parent::getModel($name, $prefix, $config); }}

    This is still a simple controller, but you can already see some meaningful code. For example, in the __constructmethod I get several different models and assign them to the view, so it will be able to get data about different objects.This is an important distinction, because each model should take care of one object and one object only. For example,if in your book view you want to get additional data about the author, do not create a getAuthorData method in thebook model; you can and should request those data directly to the author model.

    The modelThis time I removed all comments to make it even shorter.Listing 3: book model

  • jimport('joomla.application.component.model');jimport('joomla.html.pagination'); class MybooksModelBook extends JModel{ private $table = '#__mybooks_book'; private $app; public function __construct($config = array()) { parent::__construct($config); $this->app = JFactory::getApplication(); $limit = $this->app->getUserStateFromRequest( 'global.list.limit', 'limit', $app->getCfg('list_limit'), 'int' ); $limitstart = $this->app->input->get( 'limitstart', 0, '', 'int' ); $this->setState('limit', $limit); $this->setState('limitstart', $limitstart); $this->setState( 'author_id', $this->app->getUserStateFromRequest( 'com_mybooks.filters.author_id', 'author_id', 0, 'int' ) ); } public function getList() { return $this->_getList( $this->buildQuery(), $this->getState('limitstart'), $this->getState('limit') ); } public function getLast() { $query = $this->_db->getQuery(true); $query->select('*') ->from($this->table) ->orderby('created_at DESC'); $this->_db->setQuery($query,0,1); $results = $this->_db->loadObjectList('id'); return $results ? $results : array(); } public function getLastByAuthor($author_id) { $query = $this->_db->getQuery(true); $query->select('*') ->from($this->table) ->where('author_id='.$id) ->orderby('created_at DESC'); $this->_db->setQuery($query,0,1); return $this->_db->loadObject(); } public function save($data) { if (!$data) { return 0; }

    16

  • $data['created_at'] = date('Y-m-d H:i:s'); $values = implode("','", array_values($data)); $query = $this->_db->getQuery(true); $query->insert($this->table) ->columns(array_keys($data)) ->values("'".$values."'"); $this->_db->setQuery($query); if ($this->_db->execute() !== false) { return $this->_db->insertid(); } else { return 0; } } public function delete($ids) { $query = $this->_db->getQuery(true); $query->delete() ->from($this->table) ->where('id IN ('.implode(',', $ids).')'); return false !== $this->_db->execute(); } public function getPagination() { return new JPagination( $this->_getListCount($this->buildQuery()), $this->getState('limitstart'), $this->getState('limit') ); } private function buildQuery() { $query = $this->_db->getQuery(true); $query->select(*) ->from($this->table) ->orderby(created_at); foreach ($this->buildWhere() as $condition) { $query->where($condition); } } private function buildWhere() { $conditions = array(); if ($author_id = $this->getState('author_id')) { $conditions[] = "author_id = '$author_id'"; } return $conditions; }}

    This is not meant to be complete; a few other methods may be present. There are many more things that you can do

    with the data (for example reorder them) so the model often ends up as the longest class. What you see above is just asample of the the kind of code you should put in a model.

    You may have noticed that I use the JDatabaseQuery object to build my queries. For several reason that's way betterthan to build your query by yourself as a string; I strongly suggest you to try it so you will see for yourself.

    The viewListing 4: book view

  • jimport('joomla.application.component.view'); class MyBooksViewBook extends JView{ public function display($tpl = null) { $this->pagination = $this->getModel() ->getPagination(); $this->filter_author_id = $this->getModel() ->getState('author_id'); $this->books = $this->getModel()->findAll(); $this->authors = $this->getModel('Authors') ->getList(); $this->editors = $this->getModel('Editors') ->getList(); $this->addToolbar($tpl); parent::display($tpl); } protected function addToolbar($tpl) { $methodName = 'addToolBar'; if ($tpl) { $methodName .= ucfirst($tpl); } else { $methodName .= 'Default'; } $this->{$methodName}(); } private function addToolBarDefault() { JToolBarHelper::title( JText::_('COM_MYBOOKS') . ': ' . JText::_('COM_MYBOOKS_BOOK_LIST')); JToolBarHelper::addNew('create'); JToolBarHelper::preferences('com_mybooks'); JToolBarHelper::divider(); JToolBarHelper::deleteList( 'COM_MYBOOKS_BOOK_LIST_DELETE_CONFIRM', 'delete'); } private function addToolBarAdd() { JToolBarHelper::title( JText::_('COM_MYBOOKS') . ': ' . JText::_('COM_MYBOOKS_BOOK_NEW')); JToolBarHelper::apply('save'); JToolBarHelper::divider(); JToolBarHelper::back( 'JTOOLBAR_BACK', 'index.php?option=com_mybooks'); }}

    Nothing much to say; here you can see the view getting data from different models, and preparing different pages in this case only a different toolbar - according to the selected template.

    HelpersIf you've put into practice everything that you read so far in this article, you should now be using correct object-

    oriented code. Amongst other things, that means that any model in your component is related to a specific object andall its methods apply to that object and to that object only.

    What comes from this is that if you want to build a generic-purpose method, for example getCurrentDate or

    18

  • formatCurrency, the model is not the better place for it. If the method does not apply to a specific object, you don'thave any model to put it into. Here is where helpers come to... well, help.

    An helper is a class with some generic methods which can be used in several parts of your component. In most ofthe cases, a single helper for your component may be enough; for complex components, you may have additionalhelpers, each of one takes care of a specific group of tasks. It's not unusual to see an helper specifically dedicated tohandling images (uploading, fetching, resizing and so on).

    This is the kind of helper you may write:

    class mybooksHelper{ public function getCurrentDate() { // some code here } public function formatCurrency($value) { // some code here }}

    You will place this code in a file called mybooks.php into the helpers subfolder of your component. You can thencall it from any view with the following code:

    $this->loadHelper('mybooks')$helper = new mybooksHelper();$this->date = $helper->getCurrentDate();

    Table classesThe table class in Joomla is an hybrid object. It is mainly an implementation of the ActiveRecord pattern, but with

    some additional responsabilities. Anyway, this is not really important: the important thing is that you do use table andrelieve your model of one of its burden.

    Basically, the table class will act as a bridge between your application and a defined record in the database, whichcan also a be a new record.

    Listing 5: book table class

  • So for example for the book view you may have:

    an item.php layout to display a single item a list.php layout to display a list an edit.php layout to display an edit form a toprated.php layout to display the top rated books in a different way

    You may also have sublayouts, pieces of HTML that can be reused from another layout. For example, atoprated_item.php layout may hold the code to show a single item in the toprated layout. You take it away from themain file so to keep them both short and more understandable.

    The interesting about layout is that you can override them in your Joomla template. If you have never heard abouttemplate output override in Joomla you're missing a great feature, so take a look athttp://docs.joomla.org/Understanding_Output_Overrides. That page it's written for Joomla 1.5 but it's enough to get agood idea on how it works. Basically you give the web designer the chance to override the output from yourcomponent without hacking the code and keeping all data available to the original layout (reusing the view).

    Layout override is evolving quickly: in Joomla 2.5 you have the additional option to use specific layouts in yourmenu items, and in Joomla 3.x it's also possibile to have global layouts that you can share across components. I don'tcurrently have enough experience on this topic to write about it, but I hope it may be included in future versions of thisbook.

    20

  • Part 4. Other tipsThe things I have told you so far are definitely the most important things in extensions development. If you are not

    comfortable with what you read until this point, the following tips will not be very useful. If you have any doubt take astep back and try hard to apply those practices in your work. If something is not clear or you simply disagree, I wouldbe more than happy to know it, you can find my contacts at the end of the book.

    On the other hand, once the MVC and object-oriented stuff is correctly digested, it's time to take a step forward andlearn other precious skills in your extensions development. The list of tips can be very long and in fact it's endless; as Iwrite this book, I'm still learning new tricks. The following collection represent the ones that apply to most cases andhave more chance to be useful to you.

    Basic error management

    EnqueueMessageFirst of all, whenever something happens (be it a successful save or an error) you better notify the user, and this is

    where the enqueueMessage method comes to help. This is a method of the JApplication class that you can call from everywhere in your component and that will do

    what its name implies, i.e. add a message to a special queue. All enqueued messages will be then displayed by Joomlain a special area of your template, thanks to the code that you can find in any decenttemplate.

    Whenever you generate a message, you can choose a message type amongst the following three:

    message (default)warningerror

    Each template includes a basic styling for each of those types, usually by coloring them and adding a littledescriptive icon. Of course you can easily override that style with your own.

    Th e enqueueMessage method is a great way to print out debug messages without breaking the flow of thecomponent. I usually add a debug option in each of my extensions, and execute the enqueueMessage code only ifthat option is enabled. In that way, I can easily turn on and off additional informations about what's happening.

    JLogOk, the enqueueMessage is nice, but maybe you don't want to show anything to the user. In that case you can use

    the JLog class.The JLog class, very conveniently, lets you add a custom message to the general log file (/logs/error.log) or to a

    custom log file. It's a feature that's still evolving so you may see some minor changes with new Joomla versions, butright now the code to use is:

    jimport('joomla.log.log');JLog::addLogger(array('text_file' => 'mybooks.log.php'));JLog::add('This is a log record!');

    Very simple, huh? You basically open a logger on a custom file and them you write in it whatever you need.

    JError and JExceptionJError and JException are still widely used for more complex error management: they allows you, amongst other

    things, to set HTTP errors status codes. But these classes have been deprecated and will be removed from next versionsof Joomla.

    Since this book is about best practices, I won't put in it things that I haven't tried extensively. So currently I have nosuggestions about how the best way to replace those classes. As soon as a new standard comes up in the Joomla world,I will definitely update this book.

    Meanwhile, you may want to get some info about the PHP core classes to handle exceptions.

    21

  • Naming conventionsAs part of using a good coding standard, you'd better never underestimate the importance of names in your code.

    Picking the right name for a variable or a method can be extremely useful later on, when you have to understand what agiven piece of code is meant to do. It only takes a few more seconds to think of a good name. Think carefully aboutwhat a variable actually contains, and about what a method actually do: the choice of the name should come quiteeasy.

    Some examples from our experience:

    avoid abbreviations: use $version instead of $ver, or $joomla_version instead of $jVer use prefix to differentiate and clarify: use $previous_items, $retrieved_items, $saved_items in different part

    of your code instead of just $items all the time avoid similar names for different meanings: don't use $site_url and url when the second variable refers to

    something more specific, for example the URL for your component; use $my_component_url instead stick to a standard for separating words: a safe choice is to use camelCase for methods name and

    $under_score for variable names. The coding standards for Joomla (see link at the end of the article) includemore info about this topic.

    With a well chosen naming, your code will almost automatically explains itself. And that brings us to the topic ofcomments.

    CommentsAn important consequence of a good naming convention is that the number of comments you have to put in your

    code should drastically drop. Let us have an important distinction here.

    There are header comments, placed at the top of a file or just before a class or a method. This is an excellent way to document your code at the same time that you're writing it. Such comments are

    also used to automate stuff, for example you can give test informations about the method, and so on. Thus, theyare encouraged, as long as you follow a standard like phpDoc.

    Then there are inline comments, placed in the middle of your code. These have to be used more carefully. They should not be an alibi for a bad written code: if you're code is so

    ugly that you cannot understand what it does except with a comment above, you should consider improving yourcode in the first place.

    Also, do not write useless comments. The following comment is definitely not needed, since the code is quiteobvious and you're just wasting space in your source code:

    // getting old items from database$old_items = getPreviousItems();

    So basically:

    use header commentsdo your best to avoid using inline commentsif you have to, spend a little time in making sure they're clear and useful

    DocumentationIf you followed carefully until here, you already wrote some documentation without even knowing it: with phpDoc

    blocks, you wrote info about variables and methods that can be then parsed to build automatically a quick reference onyour code. That, and a good naming convention, are still the best way to document your code since any developer willbe able to understand most of it.

    22

  • Of course you may still need to write some additional documentation after that. The amount of can change greatlydepending on how many people are going to use your tool, and what level of development knowledge they got. Youmay have just a little README.txt in your root folder, or a 100 page manual; that's up to you.

    But be sure to document at least any custom requirement / procedure needed to make your software work. If yoursoftware needs additional libraries, or custom settings in Joomla, or if there are known bugs on certain conditions, youhave to write it down. Do that immediately, as an additional paragraph in your @description header, or as a separateREADME.txt.

    It's never too early to write this kind documentation: if the bugs you describe are fixed later on, it's quite easy todelete a paragraph.

    Smaller extensionsAnother important step to make your time more effective is to build smaller extensions.If you're going to build an extension that does a lot of things, it's always a good idea to split it into a set of smaller

    extensions, for example by putting most interchangeable options into plugins (think of payment methods). This notonly reduce the complexity of the code, but also allows you to reuse some of it for other projects.

    As an example, lately we had to create a system for users to edit a document online and generate a PDF from theresulting text. The main task could be splitted into several sub-features:

    allow the user to edit the documentallow the administrator to see a summary of the inserted fieldsallow both the users and the administrator to generate a PDF from the resulting document

    So we decided to create three different extensions:

    a content plugin that makes only some part of an article editable (basically creating a set of fields) a backend component that handle those fields another component that takes each article and its fields and creates a PDF

    Each of this part is easily reusable, for example, the dynamic editing of articles can also be used on its own.Try to move out of the main component each feature that is not a core feature and/or that is isolated enough to make

    sense even as a stand-alone feature. Since you're at it, make it as generic as possible so you will quickly reuse it lateron.

    Shared librariesIf it makes sense to create smaller extensions that has specific purposes, it makes even more sense to keep out of

    your component external libraries. I already told you that you should search for existing libraries both for Joomla and PHP. For example, in the same

    project that we talked about a few lines above we had to use a PDF library. We choosed TCPDF since we are quitefamiliar with it.

    This excellent library was included in Joomla 1.5 but it's not in Joomla 2.5. Browsing through the JoomlaExtensions Directory (JED), we were able to find an extension that packages the TCPDF library into a Joomla library,so we went for it. If it hadn't existed, we would have created the package ourselves, because it just doesn't make senseto include it in our main component package.

    This way, we can keep our package small and don't need to update it in case a new version of TCPDF comes out:we just have to suggest to update the related package.

    Do not package everything inside your component: make use of existing libraries and, if necessary, createadditional Joomla packages to be able to easily install more libraries.

    About version numbersEach piece of software has usually a version number: Joomla and its extensions are no exceptions. You may have

    23

  • seen different formats to define the version, but the most used and suggested is a triplet of numbers X.Y.Z, where X, Yand Z are defined as follows:

    the first is the major version: it's changed only when a significant change has been made to the overallfeatures or structure of the software (think about Joomla 2.x vs Joomla 3.x)

    the second is the minor version: it's changed everytime one or more new features or minor changes areintroduced

    the third is the release: it's usually changed at each release of the code, and often it only includes bug andsecurity fixes

    You should try to use them for what they really mean, and not just randomly. To use an example dear to us all, thedifference between Joomla 1.0 and Joomla 1.5 was more than enough - in our opinion - to require a major versionchange. In that case, Joomla 1.5 should have really been called Joomla 2.0.

    Another important thing to remember, the three numbers are not mathematically related. I've seen people switch to2.0 because they've reached 1.9 and loved too much the decimal system to think differently; but the truth is that youcan have 1.10, 1.11, and so on. It's perfectly allowed and in fact suggested. Unless of course you want to changeversion only for marketing reasons (like most of the browser do).

    Apart from versions, you may also have variants. The word "variant" is just my own term to define a differentflavour for a software. Most known example: the "Free" or "Pro" different packages for an extension. While versionnumber imply an historical evolution (one version comes after another), this is a different distinction so I don't like tocall them versions. This is especially true since most extensions developers keep all their different packages (variants)at the same version. For example, when our own GiBi AddCSS 3.6.0 will be released, it's guaranteed that GiBi AddCSSPro 3.6.0 will also be released.

    There are some who fix the variant issue by treating them as different extensions, and append the Pro suffix to theextension name. That's not what I like. If I had to decide, the variant field should become an additional field in theJoomla installer and updater. The lack of it is what pushed some of the most known Joomla extensions developers todrop the Joomla Core updater system and roll out their own.

    Joomla versionNow that we know about version number, let's see how we can use this knowledge when dealing with Joomla

    version. You already know that there is a JVersion class that will quickly tell you which Joomla version you're on. Since the third digit refers to changes which are usually very minor and don't break backwards compatibility, most

    of the time we only care about the first two digits. In other words, almost always you want to know if you're on Joomla2.5 or 3.0, you don't - usually - care if it's 2.5.10 or 2.5.11.

    The property you're looking for is "RELEASE", as in

    $jversion = new JVersion();echo $jversion->RELEASE;

    Even better, you can use the isCompatible method, as in:

    $jversion = new JVersion();if ($jversion->isCompatible('3.0') ) { // doSomething}else { // doSomethingElse}

    This internally uses the "version_compare" PHP operator to tell you if the current version is equal or newer than the

    one you're comparing it to.

    24

  • ConclusionsWell, we've seen a few things, haven't we? And this is just the start.I hope that by reading this book you will avoid all those little traps that beginners encounter while starting to

    develop Joomla extensions. Or, if you're already an experienced developer, maybe you have finally found the answerto some doubt that had been nagging you all along.

    As I have noted before the best amongst the best practices is the one called Learn. By reading books, attendingconferences and studying the work of others you will always continue to improve yourself, your time, and your code,and that is something you must never stop doing.

    UpdatesI hope to update and complete this book with additional informations, so keep an eye on

    http://extensions.gibilogic.com/blog.html or follow @GiBiLogic on Twitter to know when a new version is released.ContactsI would love to get any kind of feedback on this book. So if you have requests, critics, suggestions, you can reach

    me:

    via e-mail at [email protected] via Twitter at @f_abeni

    Thank you and have fun coding!

    25

  • Appendix: On the WebOn the following list you'll find the links referenced throughout the book.

    http://extensions.gibilogic.comGiBiLogic extensions site http://www.joomla.orgJoomla site http://extensions.joomla.orgthe Joomla Extensions Directory https://netbeans.orgNetBeans site https://github.orgGitHub site http://developer.joomla.org/5-policies/3-Joomla-Coding-Standards.htmlCoding standards for Joomla http://docs.joomla.org/Developing_a_Model-View-Controller_Component/2.5/Introductiontutorial about how to write an MVC component in Joomla http://extensions.joomla.org/extensions/core-enhancements/performance/jquery-scripts/18327JQuery Easy plugin

    26

    PART 1: prepare your environmentPart 2: everything in its right placePart 3. MVCPart 4. Other tips