Basic Class Structure
Basic Class Structure admin 22 November, 2009 - 13:48ZXAF is built from a few key components (classes/objects) and largely follows
convention over configuration and DRY.
The system core classes all resides in the exec directory. The modules are as
follows:
auditlog.php | Provides audit log messages together with a recipeint that will log all of these to the database |
config.php | Responsible for loading the correct site based config |
dbentity.php | Core of the database access, provides DbEntity and DbIterator classes |
emesary.php | The interobject messaging classes. Understanding this fully is crucial to working with ZXAF |
refmon.php | Security and access control following the reference monitor paradigm |
sysident.php | System identifications for use by the messaging |
system.php | System glue classes - provides most of the biasic objects and functions, connects to the database, provides session management etc. |
user.php | User entity - provides layer between the database table and the higher level CBF user object. |
In terms of the classes the first to understand is those related to the
database, namely DbEntity and DbIterator.
DbEntity
The DbEntity usually maps an object to a database table, providing INSERT,
UPDATE, DELETE and SELECT functions. Within the constructor the keyfield must be
defined, after which point the load(id) method can be used to
get a record from the table. If a table has multiple keys then the method of
loading is subtly different, in that you must set the fields using the
set_ methods and then call load_from_fields(), at
which point if successful true will be returned and the entity will contain the
contents of the first record that matches the fields specified. NOTE
this really works best when the fields are part of a unique key.
Example DbEntity
The following is a complete implementation of a database table.
In the constructor, it is necessary to call the parent constructor to define
the table name and the keyfield. If the table_autoid is set
then the keyfield will be assumed to be an auto_increment.
If required the set_auto_date_fields can be used to
automatically set the two defined fields to automatically contain the creation
and last update date/time for each record.
In the sample below the contstructor takes an optional key
parameter, which if present will request that the record is loaded. If this
fails then an error will be raised.
class DbTransaction extends DbEntity { function __construct($key=null) { parent::__construct("transaction","id"); $this->table_autoid = true; $this->set_auto_date_fields('created','modified'); if (!$this->init_done) $this->init(); if ($key !== null) { if(!$this->load($key)) cbf_error("Failed to load Transaction 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_created() { return $this->get_field('created'); } function set_created($v) { return $this->set_field('created',$v); } function get_modified() { return $this->get_field('modified'); } function set_modified($v) { return $this->set_field('modified',$v); } function get_user() { return $this->get_field('user'); } function set_user($v) { return $this->set_field('user',$v); } function get_item() { return $this->get_field('item'); } function set_item($v) { return $this->set_field('item',$v); } function get_quantity() { return $this->get_field('quantity'); } function set_quantity($v) { return $this->set_field('quantity',$v); } function get_amount() { return $this->get_field('amount'); } function set_amount($v) { return $this->set_field('amount',$v); } function get_type() { return $this->get_field('type'); } function set_type($v) { return $this->set_field('type',$v); } function get_paid_by() { return $this->get_field('paid_by'); } function set_paid_by($v) { return $this->set_field('paid_by',$v); } function get_reference() { return $this->get_field('reference'); } function set_reference($v) { return $this->set_field('reference',$v); } function get_reference_email() { return $this->get_field('reference_email'); } function set_reference_email($v) { return $this->set_field('reference_email',$v); } static function begin($where="") { return new DbTransactionIterator("SELECT * from `transaction` $where"); } };//class Transaction
CBF modules
Typically the DB modules as indicated above are
autogenerated by a tool, and it is by convention in the cbf/
directory that customisations to the basic database entities are performed to
provide the model.
require_once("db/transaction.php"); class CbfTransaction extends DbTransaction { function write() { $this->mark_as_unsaved('total'); return parent::write(); } function initialise_validation() { $this->set_validate_field('amount',new ValidateEntityPositiveInteger()); } function make_load_query($record_id) { $q = "select *,transaction.quantity*transaction.amount as total from ".$this->table." where ".$this->id_field."='$record_id'"; $q .= $this->extra_sql_load; return $q; } }
DbIterator
The DbIterator is used to locate one or more matching
fields. Generally it is constructed with a SELECT statement.
An example of usage is below. The $dbi variable is the
iterator, which is a container that allows moving forwards through a result set
(any other movement is not supported). if the begin method
returns true the container is valid and contains elements.
To access the DbEntity that is contained within the
DbIterator use.the current() method, which will return
an object of the type expected (as defined in the constructor of the
DbIterator.
$dbi = new DbTransactionIterator("SELECT * FROM transaction"); if ($dbi->begin()) { do { $re = $dbi->current(); $output .= $re->get_item()." - ".$re->get_amount(); }while($dbi->next()); }
Summary so far...
With the two classes DbEntity and DbIterator
it