Creating a quick and easy Mambo component

Published on Thursday, 15 April 2004 00:00
Written by Admin

Mambo Components TutorialThis is the quick component tutorial that goes with the module tutorial. This will insert "Hello World" into the database. It will also allow you to edit it, or add new messages as you see fit. This tutorial will not cover setting up categories, the search function, or page navagation. This tutorial does assume you have a very basic grasp of php.

When creating components, there are many files involved.

hello_world.xml - Component installer file
hello_world.php - Will display any frontend information.
admin.hello_world.php - Does database queries and sets up the HTML output
admin.hello_world.html.php - Handles all output.
class.hello_world.php - The database class file.
install.hello_world.php - The installer file.
uninstall.hello_world.php - The uninstall file.
toolbar.hello_world.php - Sets up the toolbar.
toolbar.hello_world.html.php - Handles the toolbar output.

 

Now that we know what all of the files are going to be, let's take a file by file look at how they function.

 

hello_world.xml - Installer file

<?xml version="1.0" ?>

<mosinstall type="component">
 <name>hello_world</name>
 <creationDate>04/15/2004</creationDate>
 <author>Doyle Lewis</author>
 <copyright>This component in released under the GNU/GPL License</copyright>
 <authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.</authorEmail>
 <authorUrl>www.mambo-hosting.com</authorUrl>
 <version>1.0</version>
 <files>
  <filename>hello_world.php</filename>
 </files>
     <install>
  <queries>
   <query>DROP TABLE IF EXISTS `jos_hello_world`;</query>
   <query>CREATE TABLE `jos_hello_world` (
    `id` INT NOT NULL AUTO_INCREMENT,
    `text` TEXT NOT NULL,
    `published` TINYINT(1) NOT NULL,
    PRIMARY KEY (`id`)
    )
   </query>

  </queries>
 </install>
 <uninstall>
  <queries>
   <query>DROP TABLE IF EXISTS `jos_hello_world`;</query>
  </queries>
 </uninstall>

 <installfile>
  <filename>install.hello_world.php</filename>
 </installfile>
 <uninstallfile>
  <filename>uninstall.hello_world.php</filename>
 </uninstallfile>
   <administration>
    <menu>Hello World</menu>
    <submenu>
     <menu act="all">Show Text</menu>
    </submenu>
    <files>
      <filename>admin.hello_world.php</filename>
      <filename>admin.hello_world.html.php</filename>
      <filename>class.hello_world.php</filename>
      <filename>toolbar.hello_world.php</filename>
      <filename>toolbar.hello_world.html.php</filename>
    </files>
   </administration>
</mosinstall>

Now let's look at how the file works:

<?xml version="1.0" ?>
XML opening container. You will need this on all xml documents.

<mosinstall type="component">
Tells Mambo that it will be installing a component

 <name>hello_world</name>
 <creationDate>04/15/2004</creationDate>
 <author>Doyle Lewis</author>
 <copyright>This component in released under the GNU/GPL License</copyright>
 <authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.</authorEmail>
 <authorUrl>www.mambo-hosting.com</authorUrl>
 <version>1.0</version>
Details of the component. All of these should be in there.

 <files>
  <filename>hello_world.php</filename>
 </files>
Any files that need to be installed in the frontend of the component. Will be installed to
components/com_hello_world/

 <install>
  <queries>
   <query>DROP TABLE IF EXISTS `jos_hello_world`;</query>
   <query>CREATE TABLE `jos_hello_world` (
    `id` INT NOT NULL AUTO_INCREMENT,
    `text` TEXT NOT NULL,
    `published` TINYINT(1) NOT NULL,
    PRIMARY KEY (`id`)
    )
   </query>
  </queries>
 </install>
The database queries that need to be run to properly setup te component. Creates 1 table with 3 fields. For any easy way to figure what to put here, create your table in phpMyAdmin and it will tell you the code to use.

 <uninstall>
  <queries>
   <query>DROP TABLE IF EXISTS `jos_hello_world`;</query>
  </queries>
 </uninstall>
Any database queries to run when uninstalling the component. This simply deletes the database table.

 <installfile>
  <filename>install.hello_world.php</filename>
 </installfile>
 <uninstallfile>
  <filename>uninstall.hello_world.php</filename>
 </uninstallfile>

Points to files with additional code for installing and uninstalling the component.

   <administration>
Everything after this point will be installed in the administrative end.

    <menu>Hello World</menu>
This is what will be displayed in the "Components" drop-down menu.

    <submenu>
     <menu act="all">Show Text</menu>
    </submenu>

This is the pop-out menu below your main menu. This also tells Mambo what function to run within your component.

    <files>
      <filename>admin.hello_world.php</filename>
      <filename>admin.hello_world.html.php</filename>
      <filename>class.hello_world.php</filename>
      <filename>toolbar.hello_world.php</filename>
      <filename>toolbar.hello_world.html.php</filename>
    </files>

All of the files that are to be installed into administrator/components/com_hello_world/.

   </administration>
</mosinstall>
Closes out the Mambo install.

 

 

hello_world.php - Frontend display

<?php
//hello_world Component//
/**
* Content code
* @package hello_world
* @Copyright (C) 2004 Doyle Lewis
* @ All rights reserved
* @ hello_world is Free Software
* @ Released under GNU/GPL License :
http://www.gnu.org/copyleft/gpl.html
* @version 1.0
**/

defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );

global $database;
$query = "SELECT * FROM jos_hello_world LIMIT 1";
$database->setQuery( $query );
$rows = $database->loadObjectList();
$row = $rows[0];

echo $row->text;

?>

Now let's look at how the file works:

defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );
This makes sure Mambo is calling the file. Very important for security.

global $database;
Sets $database as a global variable so you can use it within your function.

$query = "SELECT * FROM jos_hello_world LIMIT 1";
Selects the first entry in the jos_hello_world table in the database.

$database->setQuery( $query );
Maps your query to the $database class.

$rows = $database->loadObjectList();
Creates a variable named $rows that stores all of the database information as an array.

$row = $rows[0];
Creates a variable named $row that stores only the first value in the $rows array.

echo $row->text;
Writes the value for text to the screen.

 

admin.hello_world.php - Does database queries and sets up the HTML output

<?php
//hello_world Component//
/**
* Content code
* @package hello_world
* @Copyright (C) 2004 Doyle Lewis
* @ All rights reserved
* @ hello_world is Free Software
* @ Released under GNU/GPL License :
http://www.gnu.org/copyleft/gpl.html
* @version 1.0
**/

defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );

require_once($mosConfig_absolute_path."/administrator/components/com_hello_world/class.hello_world.php");
require_once( $mainframe->getPath( 'admin_html' ) );

switch ($act) {
 
default:
   $task = "showText";
   break;
}


switch ($task) {
  case "save":
    save( $option );
    break;
 
  case "delete":
    delete( $option, $id );
    break;
 
  case "new":
    $id = '';
    edit( $option, $id );
    break;
 
  case "edit":
    save( $option, $id[0] );
    break;
 
  case "showText":
    showText( $option );
    break;
}

function save( $option ) {
  global $database;
  $row = new mosHello_world( $database );
  
  if (!$row->bind( $_POST )) {
    echo "<script> alert('".$row->getError()."'); window.history.go(-1); </script>n";
    exit();
  }

  if (!$row->store()) {
    echo "<script> alert('".$row->getError()."'); window.history.go(-1); </script>n";
    exit();
  }

  mosRedirect( "index2.php?option=$option", "Saved" );

}


function edit( $option, $uid ) {
  global $database;
  $row = new mosHello_world( $database );
  $row->load( $uid );
  
  HTML_hello_world::edit( $option, $row );
}


function delete( $option, $cid ) {
  global $database;
  if (!is_array( $cid ) || count( $cid ) < 1) {
    echo "<script> alert('Select an item to delete'); window.history.go(-1);</script>n";
    exit;
  }
  if (count( $cid )) {
    $cids = implode( ',', $cid );
    $database->setQuery( "DELETE FROM jos_hello_world WHERE id IN ($cids)" );
    if (!$database->query()) {
      echo "<script> alert('".$database->getErrorMsg()."'); window.history.go(-1); </script>n";
    }
  }
  mosRedirect( "index2.php?option=$option" );
}


function showText($option) {
  global $database;

  # Do the main database query
  $database->setQuery( "SELECT * FROM jos_hello_world ORDER BY id" );
  $rows = $database->loadObjectList();
  if ($database->getErrorNum()) {
    echo $database->stderr();
    return false;
  }

  HTML_hello_world::showText( $option, $rows );
}

Now let's look at how the file works:

defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );
This makes sure Mambo is calling the file. Very important for security.

require_once($mosConfig_absolute_path."/administrator/components/com_hello_world/class.hello_world.php");
require_once( $mainframe->getPath( 'admin_html' ) );
Calls in the 2 files you will need. class.hello_world.php and admin.hello_world.html.php

switch ($act) {
  default:
   $task = "showText";
   break;
}
Sets a switch so that if you have an $act (action) set, it will redefine it as a $task. You will generally use $act for the main functions such as displaying the text list in this example. $task is used for things such as saving, deleting, etc.

switch ($task) {
  case "save":
    save( $option );
    break;
 
  case "delete":
    delete( $option, $id );
    break;
 
  case "new":
    $id = '';
    edit( $option, $id );
    break;
 
  case "edit":
    save( $option, $id[0] );
    break;
 
  case "showText":
    showText( $option );
    break;
}
The switch that controls your tasks. This switch tells which $task to run which function.

function save( $option ) {
Our first function. This one will save an item we create or edit.

  global $database;
Sets $database as a global variable.

  $row = new mosHello_world( $database );
This creates a new variable named $row which will store the information to insert into the database. It creates a new instance of your mosHello_world class from your class.hello_world.php file.

  if (!$row->bind( $_POST )) {
    echo "<script> alert('".$row->getError()."'); window.history.go(-1); </script>n";
    exit();
  }
If $row doesn't have any values, display the error and go back a window. Unless you are doing something wierd with entering urls on your own, this will never be used :).

  if (!$row->store()) {
    echo "<script> alert('".$row->getError()."'); window.history.go(-1); </script>n";
    exit();
  }
If it can't write to the database, report the error and go back. This will normally only occur if you are having a problem with your database.

  mosRedirect( "index2.php?option=$option", "Saved" );
If all goes well, redirect to your main option window and display the message "Saved".

function edit( $option, $uid ) {
Much of this has been covered, so we will only cover the new parts.

  $row->load( $uid );
After you have your $row defined and set to the mosHello_world class, load the row that contains the $uid value. $uid is set to the value of the $id of the item we want to edit.

  HTML_hello_world::edit( $option, $row );
Sends the $row data to admin.hello_world.html.php to be displayed.

function delete( $option, $cid ) {
Again, I will only cover the concepts not already covered.

  if (!is_array( $cid ) || count( $cid ) < 1) {
    echo "<script> alert('Select an item to delete'); window.history.go(-1);</script>n";
    exit;
  }
This checks to make sure that there has been at least one item selected to be deleted.

  if (count( $cid )) {
    $cids = implode( ',', $cid );
    $database->setQuery( "DELETE FROM jos_hello_world WHERE id IN ($cids)" );
    if (!$database->query()) {
      echo "<script> alert('".$database->getErrorMsg()."'); window.history.go(-1); </script>n";
    }
This checks to make sure there is a value for $cid (an array that holds the $ids of the items to be deleted). If there is a value, it creates a comma delimited list of the ids and stores it in $cids. It then deletes all entries with matching ids. If there is an error deleting, it will go back a screen.

function showText($option) {
This will be the main output function. This is what will create our list to display the text entries. All lines have been explained already.

 

admin.hello_world.html.php - Handles all output.

<?php
//hello_world Component//
/**
* Content code
* @package hello_world
* @Copyright (C) 2004 Doyle Lewis
* @ All rights reserved
* @ hello_world is Free Software
* @ Released under GNU/GPL License :
http://www.gnu.org/copyleft/gpl.html
* @version 1.0
**/

// ensure this file is being included by a parent file
defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );

require_once($mosConfig_absolute_path."/administrator/components/com_hello_world/class.hello_world.php");

class HTML_hello_world {

function edit( $option, &$row ) {
?>
  <script language="javascript" type="text/javascript">
    function submitbutton(pressbutton) {
    var form = document.adminForm;
    if (pressbutton == "cancel") {
      submitform( pressbutton );
      return;
    }
    submitform( pressbutton );
    }
  </script>

<form action="index2.php" method="post" name="adminForm" id="adminForm" class="adminForm">
<table border="0" cellpadding="3" cellspacing="0">
 <tr>
  <td>Text Output: </td>
  <td><input type="text" size="50" maxsize="100" name="text" value="<?php echo $row->text; ?>" /></td>
 </tr>
</table>

<input type="hidden" name="id" value="<?php echo $row->id; ?>" />
<input type="hidden" name="option" value="<?php echo $option; ?>" />
<input type="hidden" name="task" value="" />
</form>
<?php } ?>


function showText( $option, &$rows ) {
 ?>
  <script language="javascript" type="text/javascript">
  function submitbutton(pressbutton) {
    var form = document.adminForm;
    if (pressbutton == "cancel") {
      submitform( pressbutton );
      return;
    }
    submitform( pressbutton );
  }
  </script>
  <form action="index2.php" method="post" name="adminForm">
  <table cellpadding="4" cellspacing="0" border="0" width="100%" class="adminlist">
   <tr>
    <th width="20"><input type="checkbox" name="toggle" value="" onclick="checkAll(<?php echo count($rows); ?>);" /></th>
    <th class="title" width="25%">Text Output</th>
    <th width="25%">Published</th>
   </tr>
  <?php
    $k = 0;
    for($i=0; $i < count( $rows ); $i++) {
    $row = $rows[$i];
   ?>
    <tr class="<?php echo "row$k"; ?>">
     <td><input type="checkbox" id="cb<?php echo $i;?>" name="id[]" value="<?php echo $row->id; ?>" onclick="isChecked(this.checked);" /></td>
     <td><a href="#edit" onclick="return listItemTask('cb<?php echo $i;?>','edit')"><?php echo $row->text; ?></a></td>
     <td align="center">
      <?php
       if ($row->published == "1") {
         echo "<img src="images/tick.png" border="0" />";
       } else {
         echo "<img src="images/publish_x.png" border="0" />";
       }
      ?>
     </td>
     <?php $k = 1 - $k; ?>
    </tr>
 
<?php } ?>
  <input type="hidden" name="option" value="<?php echo $option; ?>" />
  <input type="hidden" name="task" value="" />
  <input type="hidden" name="boxchecked" value="0" />
  </form>

 <?php }
}
 ?>

Now let's look at how the file works:

class HTML_hello_world {
Opens the HTML output class.

function edit( $option, &$row ) {
Opens the edit function. This will show the form used to create new entries and well as edit existing ones.

  <script language="javascript" type="text/javascript">
    function submitbutton(pressbutton) {
    var form = document.adminForm;
    if (pressbutton == "cancel") {
      submitform( pressbutton );
      return;
    }
    submitform( pressbutton );
    }
  </script>

This checks when you press any of the toolbar buttons. Any form validation can be performed here as well.

<form action="index2.php" method="post" name="adminForm" id="adminForm" class="adminForm">
You can copy this verbatem to any component. It has to have all of these tags to look and function properly.

<input type="hidden" name="id" value="<?php echo $row->id; ?>" />
<input type="hidden" name="option" value="<?php echo $option; ?>" />
<input type="hidden" name="task" value="" />

The option and task fields are required for this to save or cancel correctly.

function showText( $option, &$rows ) {
This will create the list of the text entries.

    <th width="20"><input type="checkbox" name="toggle" value="" onclick="checkAll(<?php echo count($rows); ?>);" /></th>
This will select all checkboxes on the page to make publishing or deleting quicker.

  <?php
    $k = 0;
    for($i=0; $i < count( $rows ); $i++) {
    $row = $rows[$i];

$k is used to create the rollover effect on the rows. The for statement runs through all of the results.

     <td><input type="checkbox" id="cb<?php echo $i;?>" name="id[]" value="<?php echo $row->id; ?>" onclick="isChecked(this.checked);" /></td>
This will check the checkbox just for this row.

     <td><a href="#edit" onclick="return listItemTask('cb<?php echo $i;?>','edit)"><?php echo $row->text; ?></a></td>
This creates a link that will take you to the edit page when clicked.

      <?php
       if ($row->published == "1") {
         echo "<img src="images/tick.png" border="0" />";
       } else {
         echo "<img src="images/publish_x.png" border="0" />";
       }
      ?>

If the row is set to published, you will see a green checkmark, otherwise you will see a red x.

     <?php $k = 1 - $k; ?>
Sets $k equal to 1 minus itsself. If $k is 0, it will then equal 1, if it set to 1 it will then equal 0.

  <input type="hidden" name="boxchecked" value="0" />
This line is important otherwise the checkboxes will not function correctly.

 

class.hello_world.php - The database class file.

<?php
//hello_world Component//
/**
* Content code
* @package hello_world
* @Copyright (C) 2004 Doyle Lewis
* @ All rights reserved
* @ hello_world is Free Software
* @ Released under GNU/GPL License : http://www.gnu.org/copyleft/gpl.html
* @version 1.0
**/

defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );

class mosHello_world extends mosDBTable {
  // INT(11) AUTO_INCREMENT
  var $id=null;
  // TEXT
  var $text=null;
  // TINYINT(1)
  var $published=null;

  function mosHello_world( &$db ) {
    $this->mosDBTable( 'jos_hello_world', 'id', $db );
  }
}

Now let's look at how the file works:

class mosHello_world extends mosDBTable {
This line will always look like this, but change mosHello_world to what you want your class named.

  // INT(11) AUTO_INCREMENT
  var $id=null;
The commented line just gives info about the variable. The variable line has to match your db column exactly, and always set it equal to null.

  function mosHello_world( &$db ) {
    $this->mosDBTable( 'jos_hello_world', 'id', $db );
  }
This is what creates your output when you use $row = new mosHello_world( $database );

 

install.hello_world.php - The installer file.

<?php
function com_install() {
  echo "Thank you for using this component. Please contact me at This email address is being protected from spambots. You need JavaScript enabled to view it. with any questions";
}
?>

It is important to have the function com_install() call inside this file or else it will cause errors. Other than that you can have anything here you want.

 

uninstall.hello_world.php - The uninstall file.

<?
function com_uninstall() {
 echo "Thank you for using this component. Please contact me at This email address is being protected from spambots. You need JavaScript enabled to view it. with any questions";
}
?>

It is important to have the function com_uninstall() call inside this file or else it will cause errors. Other than that you can have anything here you want.

 

toolbar.hello_world.php - Sets up the toolbar.

<?php
//hello_world Component//
/**
* Content code
* @package hello_world
* @Copyright (C) 2004 Doyle Lewis
* @ All rights reserved
* @ hello_world is Free Software
* @ Released under GNU/GPL License : http://www.gnu.org/copyleft/gpl.html
* @version 1.0
**/


defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );
require_once( $mainframe->getPath( 'toolbar_html' ) );


if($task) {

  switch($task) {
    case 'new':  
    case 'edit':
 
      $act = "edit";
      break;

  }
}

if ($act) {

  switch ( $act ) {

    case 'edit':
      menuHello_world::EDIT_MENU();
      break;
   
    case 'text':
      menuHello_world::TEXT_MENU();
      break;

  }
}   

?>

Now let's look at how the file works:

require_once( $mainframe->getPath( 'toolbar_html' ) );
Works the same as requiring the admin.hello_world.html.php file in admin.hello_world.php

if($task) {

  switch($task) {
    case 'new':  
    case 'edit': 
      $act = "edit";
      break;

  }
}

"new" and "edit" will use the same toolbar.

    case 'edit':
      menuHello_world::EDIT_MENU();
      break;
This tells toolbar.hello_world.html.php which function to use.

 

toolbar.hello_world.html.php - Handles the toolbar output.

<?php
//hello_world Component//
/**
* Content code
* @package hello_world
* @Copyright (C) 2004 Doyle Lewis
* @ All rights reserved
* @ hello_world is Free Software
* @ Released under GNU/GPL License : http://www.gnu.org/copyleft/gpl.html
* @version 1.0
**/

defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );

class menuHello_world {

function TEXT_MENU() {
  mosMenuBar::startTable();
  mosMenuBar::publish('publish');
  mosMenuBar::unpublish('unpublish');
  mosMenuBar::divider();
  mosMenuBar::addNew('new');
  mosMenuBar::editList('edit', 'Edit');
  mosMenuBar::deleteList( ' ', 'delete', 'Remove' );
  mosMenuBar::endTable();
}

function EDIT_MENU() {
  mosMenuBar::startTable();
  mosMenuBar::back();
  mosMenuBar::save('save');
  mosMenuBar::spacer();
  mosMenuBar::endTable();  
}


}

?>

 

class menuHello_world {
Sets the toolbar class

function TEXT_MENU() {
  mosMenuBar::startTable();
  mosMenuBar::publish('publish');
  mosMenuBar::unpublish('unpublish');
  mosMenuBar::divider();
  mosMenuBar::addNew('new');
  mosMenuBar::editList('edit', 'Edit');
  mosMenuBar::deleteList( ' ', 'delete', 'Remove' );
  mosMenuBar::endTable();
}
This tells mosMenuBar what to print to the toolbar.The lowercase items inside the parenthesis tell admin.hello_world.php which $task to perform.

 

Well, I hope your eyes still work. This was a very basic look at how components work, and if you print it out it will still come to almost 16 pages :) I hope this helps you one your way to creating the next great Mambo component (soon to be an "Element" in 5.0)

{moscomment}