com grocer

This page is no longer maintained and will be removed when the new "Hello World" tutorial is complete

1. Introduction

In this tutorial we're going to set up a small component on your backend (administrator) that will give display, add & edit database records. For our example we have named the component "grocer", and we are going to show and edit a list of fruits. Later, we'll extend it's functionality so we can search between the fruits.

1.1 Database

Let's make a simple component that manages fruits in a grocer. We start with the database schema. Execute the following SQL statement in your MySQL client, such as PHPMyAdmin. Before doing so, replace the prefix '#_' with the prefix you chose during Joomla installation. The default is 'jos'.

CREATE TABLE IF NOT EXISTS `#__grocer_fruits` (
  `grocer_fruit_id` SERIAL,
  `name` varchar(255) NOT NULL
);

The name of the table is #__grocer_fruits. 'grocer' is the name of our component, followed by the name of the entity we want to store in this table. This name should always be plural; a table is always a collection of items. So the database table naming convention is: "dbprefix_componentname_entities".

Next we have the primary key. Every table should have one. We define it as SERIAL, which is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE.

The name of the primary key is grocer_fruit_id. Again we use the component's name 'grocer', followed by the name of the entity, in singular this time, since it describes one item. In other words the primary key name format is "componentname_entity_id"

Now we insert some sample data into the fruits table. Replace #__ with your database prefix:

INSERT INTO `#__grocer_fruits` (`name`) VALUES
    ('Orange'),
    ('Apple'),
    ('Banana');

Finally the component must be registered in the database (however, this is done automatically when installing a new component with the normal procedure through the Joomla installer)

To do this, insert the following code in the database. Replace '#_' with your database prefix ('jos' by default):

For Joomla 1.5

INSERT INTO `#__components` ( `id`, `name`, `link`, `menuid`, `parent`, 
`admin_menu_link`, `admin_menu_alt`, `option`, `ordering`, `admin_menu_img`, 
`iscore`, `params`, `enabled`) 
VALUES(NULL, 'Grocer', 'option=com_grocer', 0, 0,'option=com_grocer', 'Grocer', 
'com_grocer', 0, '', 0, '', 1)

For Joomla 1.6

INSERT INTO `#__extensions`    ( `extension_id`, `name`, `type`, `element`,
`folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, 
`params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, 
`ordering`, `state`) VALUES(NULL, 'com_grocer', 'component',
'com_grocer', '', '1', '1', '1', '0', '', '', '', '', 0, '0000-00-00 00:00:00','0','0');

1.2 Template

Next up is a template for viewing the fruits. Writing templates in Nooku Framework is like writing regular HTML and PHP, but simpler. The following code should be added to the file /administrator/components/com_grocer/views/fruits/tmpl/default.php

<ul>
<? foreach($fruits as $fruit) : ?>
    <li>
        <?=$fruit->id?>. 
        <?=$fruit->name?>
    </li>
<? endforeach; ?>
</ul>

This code will render an unordered list and for each fruit in $fruits it will render a list item with the fruit's id and name.

Some things can be noticed in this code:

  1. We are using PHP short tags:

    • <? instead of <?php
    • <?= instead of <?php echo

    If short tags are disabled in your php.ini file, Nooku will automatically rewrite them as normal tags. So you don't have to worry about compatibility issues with some server setups. Again, you can use normal tags as well, but this is more compact.

  2. We are using the PHP alternative syntax for control structures such as the foreach statement, once again for readability.

  3. We can simply use $fruits in the above example instead of $this->fruits. Nooku will by default assign fruits data to the fruits view if you don't tell it otherwise.

  4. Note that we have only added a template here, no view class. This is because Nooku will fall back on default classes whenever your component does not contain a specific class that it's looking for, in this case the fruits HTML view. So when ComGrocerViewFruitsHtml is not found, it will simply fall back on ComDefaultViewHtml, and assume that since you're requesting the fruits view, that you want to view a list of fruits.

You can also add a default view class for your component, ComGrocerViewDefault, if you want to use that as a fallback instead of ComDefaultViewHtml.

Again, take note of the following: "fruits" implies multiple fruits, while "fruit" implies a single fruit. Everywhere in Nooku, it's very important to use singular and plural forms correctly. Thanks to KInflector, Nooku translates back and forth between most English words. It even knows words like one person => many people, or one index => many indices.

1.3 Component loader

All that's left to do is add the component loader. In the file /administrator/components/com_grocer/grocer.php, we add the following code:

<?php echo KFactory::get('admin::com.grocer.dispatcher')->dispatch(); ?>

The component loader is the very first code that gets executed when you visit /administrator/index.php?option=com_grocer in your browser.

This will by default try to open the view "grocers" (plural of the component name grocer) if you don't specify a view name. To see the view you just created, visit

administrator/index.php?option=com_grocer&view=fruits 

instead. Here you should see the rendered template, displaying a list of all fruits in our database. Yes, it's that simple!

1.4 Dispatcher

To make our component use the fruits view as the default view for our component, we need to add a specialized dispatcher. In the file /administrator/components/com_grocer/dispatcher.php, we add the following code:

class ComGrocerDispatcher extends ComDefaultDispatcher 
{ 
    protected function _initialize(KConfig $config) 
    { 
        $config->append(array('controller' => 'fruits')); 
        parent::_initialize($config); 
    } 
} 

This will make Nooku use the fruits controller as a default option, making the fruits view the default view. Opening /administrator/index.php?option=com_grocer will now automatically redirect you to /administrator/index.php?option=com_grocer&view=fruits

Nooku Framework is a RAD (Rapid Application Development) Framework, which is a fancy expression for saying you don't need to write much code to get results. In time, you'll learn that Nooku does a lot of things automatically for you, based on naming conventions. Adding specific features to an extension is a matter of specialising, or in other words: Overriding, extending and customising Nooku's default behaviours to fit your needs. You'll learn how to do that in the next tutorials.

1.5 Editing data

The next step is to view and edit data. Create the form com_grocer/views/fruit/tmpl/form.php

<script src="media://lib_koowa/js/koowa.js" />
<form action="<?= @route('id='.$fruit->id) ?>" method="post" class="-koowa-form" id="fruit-form">
<input type="text" name="name" id="name" size="40" maxlength="255" value="<?= $fruit->name; ?>" placeholder="<?= @text( 'Name' ); ?>" />
</form>

The method for this form is POST as we will be changing data. In principle, use GET to display data and POST to change data.

The initial contents of the field are retrieved from the $fruit row. As we are looking at a singular view, the template loader adds the row data as the name of the view. (compare this with the plural view, where the rowset is loaded into the $fruits rowset)

How do we get to the form? We could type the url directly:

administrator/index.php?option=com_grocer&view=fruit&id=1

However, it's more useful to edit the view and make it link to the fruits directly. So in views/fruits/tmpl/default.php, change

<?=$fruit->name?>

to

<a href="<?= @route( 'view=fruit&id='.$fruit->id ); ?>">
    <?=$fruit->name?>
</a>

What does @route() do? It's a template shortcut. The template loader changes this to $this->createRoute() which in turn generates the current url. Adding parameters to the call 'view=fruit&id='.$fruit->id takes the current url and adds &view=fruit&id=($fruit->id). If view or id are already in the url, then they are replaced by the new values.

For more template shortcuts: Model_View_Controller#4.1 Template shortcuts

1.6 Adding a Model

So far we've managed to display, edit and create data without any model or sql queries. Not strictly accurate because the framework provides useful defaults for normal actions. If we now want to search our data, we need to tell the model which column to search.

Create a file com_grocer/models/fruits.php

class ComGrocerModelFruits extends ComDefaultModelDefault
{
    protected function _buildQueryWhere(KDatabaseQuery $query)
    {
        $state = $this->_state;

        if($state->search) {
            $query->where('name', 'LIKE',  '%'.$state->search.'%');
        }         
        parent::_buildQueryWhere($query);
    }
}

Save this and try the url

administrator/index.php?option=com_grocer&view=fruits&search=banana

This should now display the fruits view, showing 1 entry. We can now add the search form to the view (administrator/components/com_grocer/views/fruits/tmpl/default.php)

<form action="<?= @route() ?>" method="get" name="adminForm">
    <input type="text" id="search" name="search" value="<?= $state->search ?>" />
    <button onclick="this.form.submit();">Go</button>
</form>