All Together, As A Whole

Independent Developer and Web Site Builders Network

Christian Hent

Nooku Framework tutorial part 2: Developing of a simple backend component

This series shows you how to discover the Nooku Framework. In the first part, I explained how to set up the framework. Over this second article, you will learn how to code a simple backend component with Nooku for Joomla 1.5. For the use of Joomla! extensions, no matter in what framework they have been done, it is important that they can be easily integrated into an existing system. To anticipate, the extension which I developed for this series, is at end installable like an ordinary component and can be administrated via the Joomla! backend. The Joomla! user simply has to install the Nooku plugin first and activate it. That's all.

1. How to start developing a Joomla! extension with Nooku Framework?

Ok, this is really an interesting question. But, my first answer to that is another question: Are you pain tolerant enough to work with API's [1] that are still in flux ? If your answer is like "Yeah ! I walk on fire and swim with sharks", you meet the main prerequisite. The documentation in the wiki grows, but if you do not have at moment access to the Google group, you can not use this kind of help. In this case, you will be reliant on the provided examples. They are easy to understand and non extensive. It reaches to begin.

1.1 The Nooku coding standards and naming conventions

Please note, the most content in point 1.1.x I have copied from the official wiki.Before we dive into the component code, let's have a look at the Nooku coding standards and naming conventions. Parts of this stuff are based on well known coding standards such as PEAR, Zend Framework and Joomla! 1.5.

  • Class names are always camel cased: KClassName
  • Class names are PrefixBase[Suffix], where prefix is the namespace (K is reserved for Koowa, extensions usually use MyextBase[Suffix]
  • Class methods always start with a lowercase, while subsequent parts have an uppercase: myClassMethod()
  • Variables are lowercased and use underscores: $my_var
  • Directory and file names are always lowercased. The directory structure represents the name of the class: my/class/abstract.php contains the MyClassAbstract class
  • Constants are always uppercased and use underscores. Wherever possible, constants are declared inside a class definition. MyClass::MY_CONSTANT
  • Table names start with the placeholder prefix #__ (two underscores) and use lowercased names with underscores. The name is plural. #__my_items

1.1.1 Entity naming conventions


  • Singular: single item, row, entity, object...
  • Plural: collection, a table, a list, an array...
  • Eg: article vs articles

1.1.2 Class & file naming conventions


  • HarbourModelBoats goes in /components/com_harbour/models/boats.php
  • HarbourFilterBoatid goes in /components/com_harbour/filters/boatid.php
  • HarbourControllerBoat goes in /components/com_harbour/controllers/boat.php
  • HarbourTableBoat goes in /components/com_harbour/tables/boat.php

  • Exceptions: The views form an exception to the above rule. Views filenames use the document type that is being used to render the view.

1.1.3 Database naming conventions

When you're defining one or more tables to use in your component, it's always a good idea to put some thought in how you'll name them. Nooku doesn't force you to use any convention, but it does make your life a lot easier when you follow these best practices.
1.1.3.1 Prefix
First of all, Nooku have the #__ prefix, which is replaced with the user defined prefix. When installing Joomla, the default prefix is jos_, but it could be anything. By using #__, you never have to worry about it again.
1.1.3.2 Name
It's important to prevent name collisions. Component names in Joomla are unique, so using that for the first part of your table names will fix that: #__mycomponent_. Don't use #__com_mycomponent_, that's unnecessary luggage. Let's take a classic example: a component that manages a book collection, called com_library. The table name should reflect the contents of the table. This is always plural: you use a table to store multiple items.

  • Bad: #__library_book
  • Good: #__library_books

Even if your component uses only one table, you shouldn't use #__mycomponent. You might need more tables later, eg #__library_authors and #__library_publishers.
1.1.3.3 Primary Key
For the primary key, use the table name, in singular, followed by id.

  • #__library_books -> library_book_id
  • #__library_authors -> library_author_id

There are some very important advantages to this naming strategy. It's easier for you or other people reading your code, what tables belong to what component, and what's in them. Relations between tables are now very clear as well. #__library_books for example has two additional fields called library_author_id and library_publisher_id, which of course link an author and a publisher to the book. But more importantly, it's easy to write code now that can detect those relations automatically. As your com_library becomes smarter, you could add data mapping functionality that can understand the relations between tables, without the need to hardcode them.
1.1.3.4 SERIAL keyword
In most situations, you'll want to use auto_increment for primary keys. The SERIAL keyword is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE. BIGINT, combined with UNSIGNED, allows your primary keys to be as big as possible.
1.1.3.5 Wrapping up

1.2 About the ZN 1 component

The extension developed by me, we call it off now just ZN 1, is similar to the provided examples, but a little bit more extensive. ZN 1 uses a Mootools Sortables implementation from Stian [2] for changing list ordering with Ajax saving. This makes custom ordering as easy as can be, just DnD. Furthermore, I wrote a paginator to overide output, the ZN 1 backend pagination is rendered with the default backend template (khepri) markup. The database part consists of three tables instead of one. I added just for practical experience tables for a credits and a help/changelog page. Default toolbars are automatically created in Nooku. We treat this in more detail later. Just4fun and because a help task/button has not yet been implemented in the framework, I do it myself because it seemed so self-explanatory. And of course, because it's common Joomla! practice, ZN 1 is a multilingual component with english and german language files.

1.3 The ZN 1 MVC architecture

MVC is often seen in web applications, where the view is the actual HTML or XHTML page, and the controller is the code that gathers dynamic data and generates the content within the HTML or XHTML. Finally, the model is represented by the actual content, which is often stored in a database or in XML nodes, and the business rules that transform that content based on user actions. By decoupling models and views, MVC helps to reduce the complexity in architectural design and to increase flexibility and reuse of code. For the ZN 1 component I use the following directory architecture:

  • /controllers
  • /helpers
  • /install
  • /models
  • /views
  • manifest.xml
  • zennotes.php

1.3.1 The ZN 1 entry point

Similar to Joomla, the filename for the entry point in a Nooku based extension should have the same name such as the component. In our example this is the file zennotes.php. Let us look in the file for the entry point:

The first statement is the known Joomla! security check. Joomla's has defined('_JEXEC') in every file. This is security measure to prevent the file from being executed when called directly. However, if you write good code using Nooku Framework, everything will be in classes anyway and can not be executed when the file is called directly. The only places where it is still good to add a check is in your template files and entry points. You can use defined('KOOWA') for this. In the if-statement I check if the plugin is installed and enabled. This is required to prevent the user from error messages when Nooku Framework is not installed. At last in this file - the dispatcher. Without the above checks, all that's left to do is add the dispatcher. This is the very first code that gets executed when you visit /administrator/index.php?option=com_zennotes in your browser. You'll learn that Nooku does a lot of things automatically for you, based on naming conventions.

1.3.2 The ZN 1 models

A model aggregates data from one or more data sources. This encapsulates the data, so the rest of your code doesn't need to know what the data sources are, how to extract data from them, and how to format it in a usable way. Whenever your code uses data, it should get that data from a model's getList() or getItem() method (depending on whether you need a single entity or a set of entities). Nooku Framework implements a transparent and auto-persistent model state system . You don't need to write any JApplication::getUserStateFromRequest or setUserStateFromRequest anymore in your models'. Nooku Framework remembers your views state. For the ZN 1 component I use only one model for ZN 1 items, placed in /models directory

  • /items.php

Although I am not lazy, for credits and help, I let the Nooku factory do the work! It will create the object automatically if a model file doesn't exist. Nooku does a lot of things automatically for you, based on naming conventions.
1.3.2.1 The items model

In the items model I use the protected function _buildQueryWhere to manipulate the data set. It's no more than a simple text search filter for the backend user. The full potential of the Nooku based models, eg Fluent Interface and Model States I will describe in a separate tutorial part.

1.3.3 The ZN 1 controllers

The user interacts with the user interface in some way (for example, DnD, Click). The controller handles the input event from the user interface, often via a registered handler or callback. For the ZN 1 component I use three controllers, placed in /controllers directory:

  • /item.php
  • /credit.php
  • /help.php
1.3.3.1 The item controller

1.3.3.2 The credit controller

1.3.3.2 The help controller

The controllers for credit and help are very simple. They do nothing and are just there for better understanding. The item controller notifies the model of the user action, here resulting in a change in the item ordering when a user DnD items.

1.3.3 The ZN 1 views

If you take a look at the views in the provided harbour examples, you will find out that their names are slightly different compared to the ZN 1 Views. This difference results from the fact that I use some helpers who were not yet fully adapted to the latest Nooku code.

harbour example:

  • /boat
  • /boat/tmpl
  • /boat/tmpl/default.php
  • /boat/tmpl/form.php
  • /boats
  • /boats/tmp
  • /boats/tmpl/default.php
  • /boats/tmpl/form.php

zennotes example:

  • /item
  • /item/tmpl
  • /item/tmpl/form.php
  • /items
  • /items/html.php
  • /items/tmpl
  • /items/tmpl/form.php
  • /items/tmpl/form_items.php
1.3.3.1 The ZN 1 item view
This view is used whenever a new record is created or an existing is edited. Let us take a look at the code.

The first statement is a security check. @helper(...) is a shortcut to load helpers, here the tooltip helper. Next, we get an instance of the joomla editor. In the next line the stylesheet helper loads a CSS file, the helper accept one parameter for the location of the file. The mediaurl variable allows you to get direct access to the media folder from inside your templates. This makes it very easy to get to any media asset. It's adviced to allways use the $mediaurl variable in your template to refer to any asset that sits in your media folder. Also try to put any public asset in your media folder at all times. This will allow you to very easily move the assets to a CDN or move them around on your server. Now, all the helpers and stylesheets are loaded, let's look at the form for data entry. KView::createRoute is smart. If the route is empty then a default route will be procuded. This allows you to do things like @route() in your templates and Nooku will create the current route for you. Especially handy in forms in action attributes. @text('I love Nooku and Joomla') does the same as JText::_('I love Nooku and Joomla').

1.3.3.2 The ZN 1 items view
This view is used to list all ZN 1 items. As already mentioned, it uses a Mootools for DnD changing list ordering with Ajax saving and pagination is rendered with the default backend template (khepri) markup. And, I have played with the possibilities of the toolbars. This is also the reason why now appears an additional file html.php.

Default toolbars are created in Nooku by KToolbarDefault. Based on the plural or singular form of the toolbar name either new, edit, delete buttons or save, apply, cancel buttons are added to the toolbar automatically. The default toolbars are only created when KViewDefault is used. In other cases the default toolbar needs to be manually created through KFactory. In ZN 1, we create the toolbar manually because we need an additional button for the help task. KToolbarAbstract offers further opportunities such as reset, setTitle, setIcon...If we take a look at the credits toolbar, it should be clear how it works:

Ok, after a brief excursion into the world of toolbars, back to our view which is used to list all ZN 1 items:

Except for two small things, everything should be clear. As you can see, I don't use in ZN 1 the default helper for pagination. Instead I use my own helper, placed in components/com_zennotes/helpers/paginator.php. Out of the box Nooku Frameworks default paginator template helpers create a paginator that combines the 'item pagination' and 'search pagination' UI pattern as defined by Yahoo. The paginator is split up into different functions to allow easy overriding:

  • pagination (renders the full pagination html)
  • pages (renders only the list of pages)
  • link (renders only one page link)
  • limit (renders the limit box)

The standard paginator can be called in your templates using:

In order to improve flexibility KView::loadTemplate not auto-prefixes the template with the layout name. As a result when using loadTemplate or @template calls you need to use the full name of the template you are loading. This brings extra flexibility and improves re-use of templates in different layouts:

Last but not least the template:

1.4 Additional Infos and Links

I hope this text brings more clarity and not confusion. Please, do not understood the second part of my series about Nooku as a out-of-box tutorial. And please do not be angry if I not publish at this time the ZN 1 sources. The component I described is really not vaporware, but I do not want to publish it before a Nooku release is out. Alone out of respect. I hope you undestand this! Once Johan has its notorious 100-view-branch brought back into the trunk, I will immediately begin with the work on ZN 2. Then you can expect infos and sourcecode about fluent interfaces, model states, command chains and a lot more of this wonderfull stuff.

I would like to encourage any interested developers, to fill in the form to request access [3] to the documentation wiki, the mailing list, and other Nooku resources. It is definitiv worth! A great benefit is the provided wiki. When changes are made to the API, there's a central place for the newest and updated informations.

Links:
[1]
http://api.nooku.org/trunk/
[2]
http://ninjaforge.com/
[3]
http://www.nooku.org/en/framework/request.html

Tags: nooku

Stian Didriksen Comment by Stian Didriksen on November 9, 2009 at 5:10pm
First off, great post!

I love the amount of detail in how the process of developing your backend with Nooku works :)

Secondly, the Sortables are now working with the 100-view branch, and are updated to work with ajax pagination.
You also no longer have to set the state upon calling it and a few more nice upgrades to it.
So I'll update the com_sortables code, or maybe com_profiles instead this week.

Going to make a post soon about the ajax pagination, it's quite possibly the best script I've yet to write, complete with browser history support, will make a post about that later ;)

Thanks again for this great insight, really useful especially for those developers that are yet to get access to the koowa wiki :)
Torkil Johnsen Comment by Torkil Johnsen on November 10, 2009 at 2:57pm
In Nooku you can extend and override pretty much everything, so for paragraph 1.1.2 you could add:

HarbourViewBoats goes in /components/com_harbour/view/html.php
HarbourToolbarBoat goes in /components/com_harbour/toolbars/boat.php
HarbourToolbarButtonDelete goes in /components/com_harbour/toolbars/buttons/delete.php
HarbourMixinMenu goes in /components/com_harbour/mixins/menu.php
HarbourHelperSelect goes in /components/com_harbour/helpers/select.php

...etc :)

Oh and @Amy: When do we get decent code formatting in here? Posting code as images is hardly ideal :-/
Torkil Johnsen Comment by Torkil Johnsen on November 11, 2009 at 2:43am
To get the alternate row thingy in the last code sample, without using the extra variable $m, you can use modulo on $i:

"">
Torkil Johnsen Comment by Torkil Johnsen on November 11, 2009 at 2:44am
Uh. The code got killed by Ning.

To alternate between row0 and row1, just echo the following:
$i%2
Amy Stephen Comment by Amy Stephen on November 11, 2009 at 8:55am
If you are looking to add code to your post, change the < and > characters to the ASCII equivalents (remove the spaces in the examples, below):

< -> & # 0 6 0 ;
> -> & # 0 6 2 ;

<hello>

I have a question into Fotis on syntax highlighting suggestion he made that I'm not exactly certain how to implement.

@Chent -would you be willing to share your code in an attachment? Probably need to name it something other than .PHP but at least then people could play with your code.

Thanks for sharing this valuable resource!
Christian Hent Comment by Christian Hent on November 11, 2009 at 10:53am
Amy,

Even though I hate it to refuse a woman a desire, I must do it in this case. I will not publish the code as a component, not before B.E.E.R has been officially released. However, i can link for drag & copy to the document which is currently hosted at google. But before, I must revise some things. I hope I can do it tommorow.
Amy Stephen Comment by Amy Stephen on November 11, 2009 at 11:57am
No problem! I thought perhaps you had used images only due to Ning's poor ability to display code.

That makes perfect sense and this is not a problem at all.

Very much appreciate you sharing this work. Thanks so much!
Rateb BEN MOUSSA Comment by Rateb BEN MOUSSA on January 25, 2010 at 5:29am
Hello,
thanks for this tutorial, but I wonder to know what's the address of the google group that belong to Nooku Framework.
I've all the code from the svn and I've received response from "Johan Janssens" about code request.
Christian Hent Comment by Christian Hent on January 25, 2010 at 5:33am
Click link [3] please

Comment

You need to be a member of All Together, As A Whole to add comments!

Join All Together, As A Whole

© 2010   Created by Robert Vining on Ning.   Create a Ning Network!

Badges  |  Report an Issue  |  Privacy  |  Terms of Service

Sign in to chat!