Building a page with ZXAF.

Building a page with ZXAF. admin 9 November, 2009 - 15:11

This is a mini tutorial of how to build a page, consisting of the required entities and views to produce a fully functional page that shows the built in dynamic updating and demonstrates the ease of presenting different views.

Anything within ZXAF is built from the following core components.

The other thing that ZXAF guides you to is seperation of the layers of the logic.

  • Database
  • Business Logic (CBF)
  • UI

Step 1 - creating the entity

Most things that we create need some some of model or storage behind them. This is where we use the ZXAF DBEntity which provides both model and storage. Usually the DB entity will be extended to provide a CBF version of the entity with extra features, although this isn't required and DBEntities work just fine for most things. The reason that I usually extend the DB entity to provide a CBF version is the knowledge that probably, at some point in the future the DBEntity will need to have extra facilities. The class division convention within ZXAF dictates that the DB Entity must be a simple representation of a DB record, mainly because DB Entities are automatically created and may be replaced at any time.

The following is the SQL that will create the table in the database. This is stored in the file db/db-create-user.sql which is where the user database schem should be stored.

CREATE TABLE `help` (
    `id` int(11)  NOT NULL auto_increment,
    `category` varchar(100) default '' ,
    `section`  varchar(100) default '' ,
    `topic` varchar(100) default '' ,
    `help` text  NOT NULL,
    PRIMARY KEY  (`id`)
);

Taking this SQL file and running it through the creating tool via awk -f exec/mkdbe.awk db/db-create-user.sql will produce the db/help.php. This file provides the database entity, together with the iterators that will be used to access it

The DB entity

The following will be created by the above script, as you can see it is provides an Iterator and a Db Entity that you is used to access the DB

table_autoid = true;

        if (!$this->init_done)
            $this->init();
        if ($key !== null)
        {
            if(!$this->load($key))
                cbf_error("Failed to load Help id: $key ");
        }
    }

    function create()
    {
        if(!parent::create())
            return false;

        return true;
    }
    function get_id()             { return $this->get_field('id'); } 
    function set_id($v)           { return $this->set_field('id',$v); }
    function get_category()       { return $this->get_field('category'); } 
    function set_category($v)     { return $this->set_field('category',$v); }
    function get_section()        { return $this->get_field('section'); } 
    function set_section($v)      { return $this->set_field('section',$v); }
    function get_topic()          { return $this->get_field('topic'); } 
    function set_topic($v)        { return $this->set_field('topic',$v); }
    function get_help()           { return $this->get_field('help'); } 
    function set_help($v)         { return $this->set_field('help',$v); }
    static function begin($where="")
    {
        return new DbHelpIterator("SELECT * from `help` $where");
    }

};

Creating the CBF object

Create cbf/help.php containin the following. As explained earlier this is really just to get started. In the future extra logic related to the model may be added in here. For now there is none so a skeleton will suffice.

require_once("db/help.php");

class CbfHelp extends DbHelp
{
}

Using the CBF object

Basically you can easily create, load and delete records

// create a new record. ID is automatically assigned.
   $helpr = new CbfHelp();
   $helpr->create();
   $helpr->set_category('CAT');
   $helpr->write();

// the $helpr now contains a valid record which includes the created id, so 
// load a copy into another variable.

   $help2 = new CbfHelp($helpr->get_id());

//
// Now use an interator to dump the entire table.

   $helpit = new CbfHelpIterator("SELECT * FROM `help`"); // illustrative normally SELECTs belong in the Cbf/Db
   // or $helpt = CbfHelp::begin();
   if ($helpit->begin())
   {
      do
      {
          $record = $helpit->current();
          echo $record->get_id()." : CAT= ".$record->get_category();
      } while ($helpit->next());
   }

// now get rid off the record.

   $helpr->delete(); 

Creating the View

View creation is relatively simple. As documented elsewhere a View in ZXAF is built from a ViewItemList which is merely a set of ViewItems. Each ViewItem relates to one field from the entity. Firstly though we will need to include the pre-requesites:

require_once "views/view-main.php";
require_once "cbf/help.php";

$entity = new CbfHelp();

Now we can create a simple view by doing the following:

$vil = new ViewItemList();
$col = &$vil->add(new ViewItem("category","Category"));

$col = &$vil->add(new ViewItem("section","Section"));
$col = &$vil->add(new ViewItem("topic","Topic"));
$col = &$vil->add(new ViewItem("help","Help"));
$col = &$vil->add(new ViewItem("type","Type"));
$col->set_output_transform(new ViewItemTransformParams());
$col = &$vil->add(new ViewItem("visible","Visible"));
$col->set_output_transform(new ViewItemTransformCheckbox());

$col = &$vil->add(new ViewItem("id",""));
$col->set_output_transform(new ViewItemTransformFieldAction("helpsite","form1"));

That's the view created. Each ViewItem constructor takes two arguments the first is the field name, the second the field description (for use in headers/titles/prompts etc). The Type element has an associated ViewItemTransformParams which will take care of the translation between the numeric ID and the related record in the params table. This concept of the ViewItem providing an transformation routine to manage the output and input of individual elements is documented elsewhere and is a core part of the flexibility of the framework.

The ViewItemTransformFieldAction provides the Edit and delete buttons. Notice that it takes the ID (which is the entity ID), so that it knows which record to pull up for view or delete

The Visible element is presented via a checkbox transform. If we remove this the raw value of 1/0 will be output and may still be editted, but this is a good indication of what the ViewItemTransform concept is capable of.

The view is responsible for providing the output, which could be a input form or a list which will be presented in the form of a table. There are three main Views available by default

  • TableView - readonly tabular output of all elements as provided by the DBiterator
  • TableViewEdit - allows modification. There is added flexibility here as the edit wrapping is provided by either a click to edit version (ViewElementProviderInPlace), or by an element provider that will output either static or editable fields depending on the view (ViewElementProviderModeBased). There is also ViewElementProviderOnChange that allows elements to cause updates to other views when changed.

Now we need to create the views. All of these three views are simply a different presentation of the contents defined in the ViewItemList. Built into all of the views is the automatic update (via Ajax) when any value is changed. One the example there is a fourth representation of this entity which is the menu on the left hand side. Notice that this is also automatically updated when any changes are made.

$tv = new TableViewEdit($entity, $vil, 'formx');
$v2 = new TableView($entity, $vil, 'form2');
$v3 = new FormView($entity, $vil, 'form3');

Creating the page

All that is required now to create a complete working page (within the template provided by the standard webpage object) is to create an instance of WebPage and request that each view outputs its content.

$page = new WebPage("Help");
$page->begin();
  $page->add_body($tv->get_output(CbfHelp::begin()));
  $page->add_body($v2->get_output(CbfHelp::begin()));
  $page->add_body($v3->get_output(CbfHelp::begin()));
$page->end();

Update is performed automatically, as is save. There are clever things that can be done with the View, the ViewItemTransform and the ViewContainer to get different results, such as using Jquery to add scrolling to a table, or providing a postback based table paging