Tony Marston's Blog About software development, PHP and OOP

A Sample PHP Application

Posted on 10th November 2003 by Tony Marston

Amended on 1st August 2011

This small sample has a really big brother which can be downloaded from

Entity-Relationship Diagram
Online demonstration
Downloadable code
Installation instructions
A Challenge
Have the software generate the code for you
Amendment History


Since I started developing in PHP I have assembled a collection of standard reusable modules which enable me to create quality software in very short timescales. As a veteran developer who has experienced a variety of 2nd, 3rd and 4th generation languages, and a variety of development methodologies, I have used my experience and skill to create a development environment which encompasses quite a few different disciplines and techniques. These I have documented in the following articles:

Entity-Relationship Diagram

The database used by this software has the following structure:

Figure 1 - Entity-Relationship Diagram (ERD)

sample-application-01 (1K)

PERS-TYPE to PERSON is a one-to-many relationship.

PERSON to X-OPTION is a many-to-many relationship with PERS-OPT-XREF as the intersection. This enables the following views:

TREE-TYPE to TREE-LEVEL is a one-to-many relationship.

TREE-LEVEL to TREE-NODE is a one-to-many relationship.

TREE-NODE(SNR) to TREE-NODE(JNR) is a one-to-many relationship. This enables nodes to be related to other nodes. A node can only have one parent, but it can have any number of children.

TREE-NODE to PERSON is a one-to-many relationship.

Online demonstration

In order to demonstrate that all these different disciplines and techniques manage to work together quite nicely I have put together a small set of screens which you can run online here.

The maintenance functions for each database table all start with a LIST screen which will show all available rows in the database. Rather than show all rows at once they are split into smaller 'pages', and hyperlinks are provided at the bottom of the screen which will allow you to step forwards or backwards through all the available pages. These are known as pagination options. You can use the hyperlinks in the column headings to sort the data by that column, toggling between ascending and descending sequence.

The column headings in the LIST screens are hyperlinks which will cause the data to be sorted on that column. This will be all data which satisfies the current selection criteria, not just the contents of the current page. The sort sequence will toggle between 'ascending' and 'descending', with an image being displayed next to the column heading to indicate the current setting.

The buttons at the bottom of the screen are know as action buttons as they perform some sort of action within the current screen.

The buttons just below the screen title are known as navigation buttons as they pass control to separate scripts in order to perform whatever processing is contained within those scripts.

The checkboxes at the start of each row in the LIST screen are for selecting rows which are to be passed to a child screen (from a navigation button) for processing. Note that it is possible to select multiple rows before pressing a navigation button as the detail screen will offer a set of scrolling options (similar to the pagination options) to allow the user to move backwards and forwards through the selected rows.

There is a help button in each screen which will display online help text.

Downloadable Code

You can download all the relevant code from here so that you can run it in your own environment and examine the source code at your leisure. The zip file contains the following:

This code has been tested with the following PHP versions:

It has also been tested with the following MySQL versions:

It has also been tested with PostgreSQL version 8, Oracle 10g Express Edition and SQL Server 2008 R2 Express Edition.

When you run each script it will dump its XML data into a separate file in the XSL folder so that you can see exactly what is being input into the XSL transformation process. I have found this to be very useful when debugging.

In case you are interested the IDE that I use was PHPEdit, then I switched to Zend Studio, but I now use Nusphere PhpED.

Enjoy! Don't applaud, just throw money!

Installation instructions

I am assuming that you already have a working PHP installation in which you have identified a directory as the "document root" (<docroot>). The zip file starts with a directory called "sample". You need to perform the following steps:

A Challenge

I believe that I have created a development environment which allows a programmer to create working components quite rapidly. If you do not believe me then I invite you to take this challenge. Create your own family of forms by taking the following steps:

  1. Create a test database table with a reasonable selection of columns. You can use my PERSON table as an example as this contains a mixture of string, date and numeric fields. It also has a candidate key as well as a primary key.
  2. Create a class for this table named <tablename> This must be a subclass of my default_table as defined in
  3. Create a screen structure file for the List View called <tablename> and the Detail View called <tablename> You will find it easier to copy some existing files and change them.
  4. Create 6 component scripts named <tablename>_X.php where X is add, del, enq, list, search and upd. Use my person_X.php scripts as examples.
  5. Add the list screen as a hyperlink to my index page and off you go!

If you take a look in the infrastructure FAQ you will see an example laid out for you.

Unless you take too many coffee breaks you should be able to complete all these tasks in 60 minutes. That makes an average of 10 minutes per component. Is your current development methodology as productive as that?

Have the software generate the code for you

If you wish to see something even faster then you should check out this sample's big brother at which has code generation facilities built into the Data Dictionary. With this you can perform the following:

This means that starting with nothing more than a database schema you can create working transactions to maintain the contents of each of those tables without having to write a single line of code. Is your current development methodology as productive as that?

Amendment history:

1st Aug 2011 Added new DAO class to access an SQL Server database, as documented in Creating a SQL Server Driver.
28th Sep 2010 Updated the code which modifies the WHERE string to use more sophisticated regular expressions.
23rd Mar 2007 Modified all XSL stylesheets to improve performance.
15th Jan 2007 Added new DAO class to access an Oracle database, as documented in Creating an Oracle Driver.
5th Dec 2006 Updated all XSL files to same versions as in Radicore, and made necessary adjustments to the code.
Added Have the software generate the code for you.
19th Jun 2006 Modified all images, CSS and XSL files which deal with tree structures.
21st May 2006 Updated all XSL stylesheets so that they are in line with my full development framework.
2nd Apr 2006 Fixed a bug in the getCount() method when dealing with a GROUP BY clause in a nested query. My thanks to Kyle Brost for spotting this bug and providing a fix.
8th Jan 2006 As it appears that the PHP developers are going to introduce case-sensitivity for class names and function names (stupid idea!) I have converted all my class names to lower case.
11th Dec 2005 Added the ability to perform XSL transformations client-side as well as server-side, as documented in Performing client-side XSL transformations.
11th Oct 2005 Included a user defined function which enables the CONCAT() function in PostgreSQL. See sql/postgresql/function_concat.sql for details.
10th Sept 2005 Included a new class for accessing a PostgreSQL database as discussed in Creating a PostgreSQL driver for the Radicore Development Infrastructure.
15th July 2005 Modified the source code to include the features described in Internationalisation and the Radicore Development Infrastructure. This has involved changing the STAR_SIGN field on the PERSON table from type ENUM to CHAR(3) so that the values can be displayed in more than one language.
27th June 2005 Modified the source code to include an unFormatData() function so that when constructing WHERE clauses for SELECT statements any fields which have been formatted for output to the user, such as dates, are unformatted before being passed to the database.
25th June 2005 Modified the source code after renaming transaction pattern Multi 1 to Multi 2.
21st June 2005 Modified the source code to deal with new features in the screen structure scripts.
25th May 2005 Although I do not use them I have modified the code to deal with the 'auto_increment' option on primary keys.
28th Mar 2005 Move all table classes into a separate CLASSES subfolder.
12th Mar 2005 Added a new item called 'picture' to PERSON table which identifies an image to be displayed.
20th Jan 2005 Fixed a bijoux bugette in the validateDelete() method in the generic table class.
16th Jan 2005 Amended code which converts WHERE string to and from arrays to deal with more situations.
5th Dec 2004 Amended code so that a cascade delete will now traverse as many levels as is necessary instead of being limited to just one.
25th Nov 2004 Added an Entity-Relationship Diagram.
30th Aug 2004 Added a new field to the PERSON table which will demonstrate the use of a popup form. This will allow the user to pick a node from the tree structure of type 'Organisation'.
25th Aug 2004 Added new components which demonstrate the contents of article A flexible Tree structure.
8th Aug 2004 Added file DML.MYSQLI.CLASS.INC which contains all the function calls to access MySQL versions 4.1 and above. Amended STD.TABLE.CLASS.INC so that upon detecting the availability of the 'mysqli_' functions it will instantiate this new class.
4th Aug 2004 Renamed INCLUDE.XML.INC to INCLUDE.XML.PHP4.INC and created INCLUDE.XML.PHP5.INC so that the correct version can be included at runtime depending on which version of PHP is being used.
  • The PHP 4 version uses the DOM XML and XSLT (Sablotron) functions.
  • The PHP 5 version uses the DOM and XSL functions.
26th May 2004 Changed STD.DML.CLASS.INC to DML.MYSQL.CLASS.INC so that the filename identifies which DBMS engine it serves. This will allow different DML classes for different DBMS engines to exist at the same time. Each table subclass will know which file to access at runtime, making it possible for different database tables to be accessed through different DBMS engines within the same transaction.
8th May 2004 Added functions to maintain the OPTION table and the PERS_OPT_XREF table which exists in a 'many-to-many' relationship between PERSON and OPTION. There is a function which will maintain PERS_OPT_XREF for a selected PERSON, and another for a selected OPTION.
18th Mar 2004 Restyled all screens to give a different 'look and feel'.
22nd Dec 2003 Added a button to all screens to activate online help.
3rd Dec 2003 Added A Challenge.