Basic Application Development with Nennius (part 1)


One of the things that makes PHP so popular is its rapid development speed. Using PHP, a developer can create basic dynamic elements within a standard webpage in no time at all. This concept also applies to larger, more comprehensive projects. However, most programmers will agree that there is no need to re-invent the wheel. So the question then becomes: when is it more efficient to use a pre-developed library or framework rather than develop an application from scratch? That of course depends on a wide variety of things, but one of the key factors is whether the library or framework in question is re-usable for future projects.

About Nennius

Several months ago, I found myself developing a time and expense tracking tool for a client. Although more complex in nature than most of the data-management tools I had developed for previous clients, it still had a large amount of features in common with those other systems. After thinking about this for some time I decided to scrap the project as it was, and instead develop a set of re-usable libraries that offered all of the same features. To make a long story short, the result of this was Nennius: an object-oriented application engine specifically designed to aid in the rapid development of PHP projects.

This article will discuss creating up a basic web application using the Nennius framework. Part 2 will then look at a few of the more advanced features available to Nennius developers. If you wish to follow along, please download the latest version of Nennius from Source Forge. If you would like to learn more about the Nennius project after reading this article, please visit the official Nennius website.

Initializing a New Nennius Application

Similar in some respects to Tomcat, Nennius is itself an application engine. In turn, it allows developers to create multiple, fully-customizable web applications that may be run simultaneously on top of a single instance of the engine. Each web application resides in a folder located within the ‘/nennius/webapps/’ directory. So the first step in creating a Nennius application is to create a folder within that directory. For the purposes of this article, we will develop a basic web application that manages news releases for a corporate website. Our folder will be named “news”.

Once our folder has been created, the next step is to define a basic configuration for our application. The Nennius bundle includes a sample web application, and I recommend that user’s make a copy of the “application.defaults.php” file provided with that example when creating a new app. We will want to make a copy of this file with the same name and place it into our ‘news’ directory. The purpose of the defaults file is to define basic values for all application variables (editable and non-editable). These values will then be used by the Nennius engine to drive the application.

(Note: it is recommended for advanced projects that the developer also create a file named ‘application.config.php’ to store all editable values. This config file then allows a user to customize certain variables to his or her preference, while leaving the initial configuration un-touched. This is important for several reasons: it keeps editable variables separate from non-editable variables, and it also allows for an easy start-over point in the instance that the config file itself is somehow corrupted.)

The last step in initializing a Nennius web application is defining a menu. This can be done for now by copying the file ‘/nennius/webapps/welcome/’ into our ‘news’ folder, and then modifying it to fit our purposes. We'll come back to this shortly, but first let's take a look at how to setup our basic configuration.

Configuring an Web Application

For the purposes of our example application, our default configuration file will contain the following:
# name of application
$GLOBALS['nennius_application_name']	= 'News Manager';

# absolute path to current application on web server
$GLOBALS['nennius_application_path']	= '/nennius_server_path/webapps/news/';

# absolute URL to current application
$GLOBALS['nennius_application_url']	= '';

# Nennius database connection variables - configure to match your SQL setup $GLOBALS['nennius_db_type'] = 'mysql'; # ex. 'mysql', 'postgresql', 'oracle' $GLOBALS['nennius_db_ip'] = 'localhost'; $GLOBALS['nennius_db_user'] = 'user'; $GLOBALS['nennius_db_pass'] = 'pass'; $GLOBALS['nennius_db_name'] = 'news'; ?>
Although a wide variety of variables may be set for more advanced projects, only those listed above are required for a Nennius application. The variables names as well as the accompanying comments are self-explanatory, so we will not spend any more time discussing the configurations file in this article. (Part 2 however will discuss many of the more advanced configuration properties.)

Defining an Application’s Menu

The next step in creating a Nennius application is defining a menu structure. The menu configuration file ('’) contains two basic variables. The first, $nennius_menu_array, is an array specifying menu category names as keys, which in turn hold child arrays containing menu options for the category in question. Put another way each menu link is a self-describing array, contained by a larger array holding similarly grouped items, which is itself contained by yet another array – $nennius_menu_array.

For the purposes of our sample application, we will create one menu category, "Admin Options", and 2 menu options: “Manage Releases” and “Corporate Website”. Example code for doing this is provided below:
# include config_defaults file for threshold values
# NOTE: ignore a failed include for the purposes of the admin GUI
@ include_once '../../config.defaults.php';

# intiialize nennius menu array
$nennius_menu_array	= NULL;

# Manage Releases - links to Nennius page for adding & removing news releases
$admin_options_array[] 	= ( array(	'menu_display_name'	=> 'Manage Releases',
					'menu_hyperlink'	=> 'index.php',
					'menu_threshold'	=> $GLOBALS['ADMIN'] ) );

# Corporate Website - links to external corporate website to view changes in realtime
$admin_options_array[]	= ( array(	'menu_display_name'	=> 'Corporate Website',
					'menu_hyperlink'	=> '',
					'menu_threshold'	=> $GLOBALS['PUBLIC'] ) );
# add all menus to nennius menu array
$nennius_menu_array['Nennius Menu']	= $admin_options_array;

# globalize nennius menu array for access by Display Template
$GLOBALS['nennius_menu_array']		= $nennius_menu_array;
As you can see, each menu item contains several attributes: display name, hyperlink, and threshold. Perhaps the only one of these attributes that may not be self-explanatory upon first examination is the threshold. Nennius allows for 6 basic threshold levels: PUBLIC, CLIENT, USER, REVIEWER, MANAGER, and ADMIN. Every user is assigned a level, and in turn those levels are used to determine what content a user has access to as well as what operations a user may preform on specific content. For purposes of the menu configuration, a threshold level defines the minimum threshold required for a user to view a menu link. In our example above, any user (even one who has not yet logged in) will be able to view the "Corporate Website" link, but only ADMIN users will be able to view the link entitled "Manage Releases".

That's it. We've now defined a basic menu for our 'news' web app. (Note: Nennius will automatically generate 'login' and 'logout' menu options as well when appropriate.)

Creating SQL Tables

In many cases, Nennius will be configured to manage pre-existing data. However, this is not the case for our sample application. We will need to create three basic SQL tables: one to hold Nennius users, one to hold the news releases we will be creating, and another to act as a Threshold lookup table. The queries for doing this are shown below:
-- create basic news table to contain date, title, and body of release
  `id` int(3) unsigned zerofill NOT NULL auto_increment,
  `datetime` datetime NOT NULL default '0000-00-00 00:00:00',
  `title` varchar(100) NOT NULL default '',
  `body` text NOT NULL,
  PRIMARY KEY  (`id`)

-- create nennius user table holding basic information about user record(s)
CREATE TABLE `users` (
  `id` int(2) unsigned zerofill NOT NULL auto_increment,
  `username` varchar(35) NOT NULL default '',
  `password` varchar(35) NOT NULL default '',
  `name` varchar(35) NOT NULL default '',
  `email` varchar(35) NOT NULL default '',
  `threshold_id` int(2) unsigned zerofill NOT NULL default '00',
  PRIMARY KEY  (`id`),
  KEY `threshold_id` (`threshold_id`)

-- insert default user (for demo purposes) of 'admin' w/ password 'admin'
INSERT INTO `users` VALUES (01, 'admin', 'admin', 0, '', 06);

-- create threshold lookup table
CREATE TABLE `thresholds` (
  `id` int(2) unsigned zerofill NOT NULL auto_increment,
  `name` varchar(25) NOT NULL default '',
  `value` int(3) unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`)

-- insert all Nennius-supported threshold types into lookup table
INSERT INTO `thresholds` VALUES (01, 'PUBLIC', 0);
INSERT INTO `thresholds` VALUES (02, 'CLIENT', 10);
INSERT INTO `thresholds` VALUES (03, 'USER', 30);
INSERT INTO `thresholds` VALUES (04, 'REVIEWER', 50);
INSERT INTO `thresholds` VALUES (05, 'MANAGER', 70);
INSERT INTO `thresholds` VALUES (06, 'ADMIN', 90);
As you can see, the structures for our news releases and users tables are fairly basic. The threshold table may not be as intuitive, but we will take a closer at this in Part 2. For now we will continue on to setup our application.

Creating a Nennius Component

Now that we have setup our basic web application, it is time to consider the data we will be managing. Since our example application is intended only to manage news releases for a corporate website, our component will be relatively basic. There are a variety of ways to create Nennius components, some simple and some complex. All component logic can be contained within a single file, or split apart into multiple files. The latter is recommended in the Nennius documentation. So for our component we will split our logic into three files, each descibed below:
/news/index.php			- instantiates news component - this is our entry-point file
/news/components/news.php	- contains all programming logic & describes DB table structure
/news/descriptors/news.php	- defines basic component info & threshold permissions
At first, this may seem overly compicated. However it is a good development habit to design projects to be easily scalable. By splitting these three areas of logic into their own files, we will make upgrading and enhancing our system (described in Part 2 of this article) a much easier task. Furthermore, creating each file in its own descriptive folder area will result in a lot less clutter for larger Nennius projects.

Defining the Entry-Point

Since our application will only be managing one type of data, we have chosen to name our entry point 'index.php'. An entry-point file simply includes and instantiates our component class, so defining it will be relatively simple:
# define location of component & descriptor files
$component_file		= 'components/news.php';
$descriptor_file	= 'descriptors/news.php';

# include parent nennius_component class
include_once "../../nennius.component.php";
include_once $component_file;

# create a new object to kick things off
# NOTE:	New object will extend nennius_component class,
#	so in order to instantiate it must be passed a descriptor file.
#	optionally, we will also pass a reference to an external fields file,
#	to better seperate our areas of logic
new news( $descriptor_file );
As you can see, all our index file does is include our component file (along with the class it extends) and then instantiates it by passing it a reference to our descriptor file. Both the component and descriptor files have been mentioned briefly, but let's now take a closer look at each.

The Descriptor File

The descriptor file is where we store information pertaining to the component as a whole. This information ranges from the name of the component (displayed in the browser's title area) to the name of the DB table containing our component's data. This is different than the component file, as it does not describe the data's attributes, merely its overall behavior. Our descriptor file will contain the following:
# set	display name for component
$GLOBALS['g_main_display_name']		= 'News Releases';

# set primary db table name
$GLOBALS['g_db_primary_table']		= 'news';

# set primary key for main db table
$GLOBALS['g_db_primary_table_key']	= 'id';

# set (optional) primary display field for db table
# NOTE: this field is used as the main display name for a record
$GLOBALS['g_db_primary_table_name']	= 'title';

# set required min. threshold for overall access
# NOTE: this should be the same as the threshold specified in
$GLOBALS['g_threshold_overall']		= $GLOBALS['ADMIN'];

The Component File

As previously stated, the component file describes attributes of our data. It also contains any custom programming logic that a developer wishes to add on top of a Nennius application. (This will be discussed in greater detail in Part 2.) Our component file will contain the following:
# basic news component
class news extends nennius_component {

	# store class-wide reference to control object
	# NOTE:	this object is created by the nennius_component class, so the 
	#	main purpose of this var declaration is to make sure that the 
	#	developer is aware that the nennius_control class is accessible
	var $nennius_control				= NULL;

	# sets up necessary internal vars, creates new control object 
	# and passes self-reference to it
	function news(	$p_component_descriptor_file	) {
		# call out to constructor of parent class with descriptor file
		$this->nennius_component(	$p_component_descriptor_file );
	} # END news
	# retrieves and returns assoc. array containing db column info
	function get_info_db_array() {	
		$f_db_info_array	= NULL;
		# define primary key attribute for news table
		$f_db_info_array['id'] = (
			array (
				'db_field_name' 	=> 'id',
				'db_field_type' 	=> 'int',
				'db_field_length' 	=> 3,
				'db_primary_key'	=> TRUE,
				# field is hidden from visibility at all times
				'hidden_all' 		=> TRUE
		# date & time when article was initially posted / releasesd
		$f_db_info_array['datetime'] = (
			array (
				'db_field_name'		=> 'datetime',
				'db_field_display'	=> 'Date / Time',
				'db_field_type'		=> 'datetime',
				'db_field_length' 	=> 19,
				'db_field_required'	=> TRUE,
				# set default value to be current date & time
				'update_default'	=> date( 'Y-m-d H:i:s' ),
				# set attribute to be searchable by min & max date range
				'search_date_range'	=> TRUE
		# title of news release
		$f_db_info_array['title'] = (
			array (
				'db_field_name' 	=> 'title',
				'db_field_display' 	=> 'Title',
				'db_field_type' 	=> 'char',
				'db_field_length' 	=> 100,
				# set field to be searchable using a partial-match criteria
				'input_search_type'	=> 'TEXT',
				'search_partial'	=> TRUE,
		# main body of article
		$f_db_info_array['body'] = (
			array (	
				'db_field_name' 	=> 'body',
				'db_field_display'	=> 'Article',
				'db_field_type' 	=> 'char',
				# define size of textarea input
				'input_update_type'	=> 'TEXTAREA',
				'input_update_rows'	=> 10,

				# hide field from search & view modes
				'hidden_search'		=> TRUE,
				'hidden_view'		=> TRUE
		# after all attributes have been setup, return array
		return $f_db_info_array;
	} # END get_info_db_array()

} # END news class
As you can see, only two functions are required for our component class. One, the descriptor, simply defers to the nennius_component class (which in turn sets up and instantiates all necessary API classes). The other, get_info_db_array(), creates and returns an associative array describing our data's attributes. The array values listed above should be self-explanatory, but for a detailed list of all possible array keys and values please refer to the Nennius developer's documentation.


We have now completed our example Nennius web application. To use the application, you simply need to direct your web browser to the 'index.php' file we defined above and enter your login information: 'admin' / 'admin'. As an alternative you may also access this application online at:

Once you have logged in you will be able to preform standard data-management operations (such as add, modify, delete, search, sort, etc.) on the news releases data that you enter. For more information about how to preform these operations, please refer to the Nennius user's documentation.

We will continue in Part 2 by expanding the scope of this application, and taking a look at some of the advanced features Nennius offers its developers. We will also look at creating other components and defining their relationship to the 'news' component we have already created. If you have any questions in the meanwhile, please feel free to visit the Nennius user forums.