Difference between revisions of "FOGController"
m (→Overview: added Category:Development) |
(No difference)
|
Latest revision as of 16:49, 30 September 2011
Contents
Overview
FOGController is a new Chainable PHP Class developed for use in FOG web applications. This Class acts as an abstraction layer between PHP's data and its database entry.
The Class is an abstract Class, providing a base for FOG Classes to build from. All you need to do is describe to the Class the relationship between your Database fields and common names used when accessing the data.
- Please note all of this is developmental and could change at any moment
Variables & Methods
Variables and their defaults
abstract class FOGController
{
// Table
protected $databaseTable = '';
// Name -> Database field name
protected $databaseFields = array();
// Do not update these database fields
protected $databaseFieldsToIgnore = array(
'createdBy',
'createdTime'
);
// Allow setting / getting of these additional fields
protected $additionalFields = array();
// Required database fields
protected $databaseFieldsRequired = array(
'id',
'name'
);
// Store data array
protected $data = array();
// Auto save class data on __destruct
protected $autoSave = false;
// DEBUG mode - print all Errors & SQL queries
protected $debug = false;
}
Methods
$this public function __construct($data) $this public function __destruct() $this public function set($key, $value) $this public function get($key) $this public function add($key, $value) $this public function remove($key, $object) boolean public function save() boolean public function load($field = 'id') boolean public function destroy($field = 'id') void public function error($txt, $data = array()) void public function info($txt, $data = array()) boolean public function isValid() boolean private function isTableDefined() string public function __toString()
Example
This is an example of FOG's up coming OS Class in v0.33
OS.class.php
class OS extends FOGController
{
// Table
protected $databaseTable = 'os';
// Name -> Database field name
protected $databaseFields = array(
'id' => 'osID',
'name' => 'osName',
'description' => 'osDescription'
);
}
Only $databaseFields is required.
Providing $databaseTable gives access to FOGControllers save() and load() functions.
Example: Add new OS
// New OS Object
$OS = new OS();
// Set name -> Set description -> Save to database (returns true on success)
if ($OS->set('name', 'Windows 8')->set('description', 'more junk')->save())
{
// id property is added after a successful save
$FOGCore->setMessage(sprintf('OS Added: ID: %s, Name: %s', $OS->get('id'), $OS->get('name')));
}
else
{
$FOGCore->setMessage(sprintf('Failed to add: %s', $OS->get('name')));
}
// Redirect back to self
$FOGCore->redirect();
Example: Update an Existing OS
// OS ID Variable
$id = '1';
// Load OS - auto loads from database when ID is passed
$OS = new OS($id);
// Is OS valid? (was it loaded from the database correctly)
if ($OS->isValid())
{
print_r($OS);
}
Class
FOGController.class.php
<?php
// Blackout - 1:28 PM 23/09/2011
abstract class FOGController
{
// Table
protected $databaseTable = '';
// Name -> Database field name
protected $databaseFields = array();
// Do not update these database fields
protected $databaseFieldsToIgnore = array(
'createdBy',
'createdTime'
);
// Allow setting / getting of these additional fields
protected $additionalFields = array();
// Required database fields
protected $databaseFieldsRequired = array(
'id',
'name'
);
// Store data array
protected $data = array();
// Auto save class data on __destruct
protected $autoSave = false;
// DEBUG mode - print all Errors & SQL queries
protected $debug = true;
// Database Class
protected $db;
// Construct
public function __construct($data)
{
try
{
// Error checking
if (!count($this->databaseFields))
{
throw new Exception('No database fields defined for this class!');
}
// Database
$this->db = $GLOBALS['db'];
// Add incoming data
if (is_array($data))
{
// Iterate data -> Set data
foreach ($data AS $key => $value)
{
$this->set($key, $value);
}
}
// If incoming data is an INT -> Set as ID -> Load from database
elseif (is_numeric($data))
{
if ($data <= 0)
{
throw new Exception(sprintf('ID less than or equal to 0: Data: %s', $data));
//return false;
}
$this->set('id', $data)->load();
}
// Unknown data format
else
{
throw new Exception('No data array or ID passed!');
}
}
catch (Exception $e)
{
$this->error('Create Class Failed: Class: %s, Error: %s', array(get_class($this), $e->getMessage()));
}
return $this;
}
// Destruct
public function __destruct()
{
// Auto save
if ($this->autoSave)
{
$this->save();
}
}
// Set
public function set($key, $value)
{
try
{
$databaseFieldsRev = array_flip($this->databaseFields);
if (!array_key_exists($key, $this->databaseFields) && !in_array($key, $this->additionalFields) && !array_key_exists($key, $databaseFieldsRev))
{
throw new Exception('Invalid data being set');
}
if (array_key_exists($key, $databaseFieldsRev))
{
$key = $databaseFieldsRev[$key];
}
$this->data[$key] = $value;
}
catch (Exception $e)
{
$this->error('Set Failed: Class: %s, Key: %s, Value: %s, Error: %s', array(get_class($this), $key, $value, $e->getMessage()));
}
return $this;
}
// Get
public function get($key)
{
return (isset($this->data[$key]) ? $this->data[$key] : '');
}
/*
public function __set($key, $value)
{
return $this->set($key, $value);
}
public function __get($key)
{
return $this->get($key);
}
*/
// Add
public function add($key, $value)
{
try
{
$databaseFieldsRev = array_flip($this->databaseFields);
if (!array_key_exists($key, $this->databaseFields) && !in_array($key, $this->additionalFields) && !array_key_exists($key, $databaseFieldsRev))
{
throw new Exception('Invalid data being set');
}
if (array_key_exists($key, $databaseFieldsRev))
{
$key = $databaseFieldsRev[$key];
}
$this->data[$key][] = $value;
}
catch (Exception $e)
{
$this->error('Add Failed: Class: %s, Key: %s, Value: %s, Error: %s', array(get_class($this), $key, $value, $e->getMessage()));
}
return $this;
}
// Remove
public function remove($key, $object)
{
try
{
$databaseFieldsRev = array_flip($this->databaseFields);
if (!array_key_exists($key, $this->databaseFields) && !in_array($key, $this->additionalFields) && !array_key_exists($key, $databaseFieldsRev))
{
throw new Exception('Invalid data being set');
}
if (array_key_exists($key, $databaseFieldsRev))
{
$key = $databaseFieldsRev[$key];
}
foreach ((array)$this->data[$key] AS $i => $data)
{
if ($data->get('id') != $object->get('id'))
{
$newDataArray[] = $data;
}
}
$this->data[$key] = (array)$newDataArray;
}
catch (Exception $e)
{
$this->error('Remove Failed: Class: %s, Key: %s, Object: %s, Error: %s', array(get_class($this), $key, $object, $e->getMessage()));
}
return $this;
}
// Save
public function save()
{
try
{
// Error checking
if (!$this->isTableDefined())
{
throw new Exception('No Table defined for this class');
}
// Variables
$fieldData = array();
$fieldsToUpdate = $this->databaseFields;
$fieldToName = array_flip($this->databaseFields);
// Remove unwanted fields for update query
foreach ($this->databaseFields AS $name => $fieldName)
{
if (in_array($name, $this->databaseFieldsToIgnore))
{
unset($fieldsToUpdate[$name]);
}
}
// Build insert key and value arrays
foreach ($this->databaseFields AS $name => $fieldName)
{
$insertKeys[] = $this->db->sanitize($fieldName);
$insertValues[] = $this->db->sanitize($this->get($name));
}
// Build update field array using filtered data
foreach ($fieldsToUpdate AS $name => $fieldName)
{
$updateData[] = sprintf("`%s`='%s'", $this->db->sanitize($fieldName), $this->db->sanitize($this->get($name)));
}
// Insert & Update query all-in-one
$query = sprintf("INSERT INTO `%s` (`%s`) VALUES ('%s') ON DUPLICATE KEY UPDATE %s",
$this->db->sanitize($this->databaseTable),
implode("`, `", $insertKeys),
implode("', '", $insertValues),
implode(', ', $updateData)
);
// INFO
$this->info($query);
if (!$this->db->query($query))
{
// Query failed
throw new Exception($this->db->error());
}
// Database query was successful - set ID if ID was not set
if (!$this->get('id'))
{
$this->set('id', $this->db->insert_id());
}
// Success
return true;
}
catch (Exception $e)
{
$this->error('Database Save Failed: Class: %s, ID: %s, Error: %s', array(get_class($this), $this->get('id'), $e->getMessage()));
}
// Fail
return false;
}
// Load
public function load($field = 'id')
{
try
{
// Error checking
if (!$this->isTableDefined())
{
throw new Exception('No Table defined for this class');
}
if (!$this->get($field))
{
throw new Exception(sprintf('Operation field not set: %s', strtoupper($field)));
}
// Variables
$fieldToName = array_flip($this->databaseFields);
// Build query
if (is_array($this->get($field)))
{
// Multiple values
foreach ($this->get($field) AS $fieldValue)
{
$fieldData[] = sprintf("`%s`='%s'", $this->db->sanitize($this->databaseFields[$field]), $this->db->sanitize($fieldValue));
}
$query = sprintf("SELECT * FROM `%s` WHERE %s",
$this->db->sanitize($this->databaseTable),
implode(' OR ', $fieldData)
);
}
else
{
// Single value
$query = sprintf("SELECT * FROM `%s` WHERE `%s`='%s'",
$this->db->sanitize($this->databaseTable),
$this->db->sanitize($this->databaseFields[$field]),
$this->db->sanitize($this->get($field))
);
}
// INFO
$this->info($query);
// Did we find a row in the database?
if (!$queryData = $this->db->query($query)->fetch()->get())
{
throw new Exception($this->db->error());
}
// Loop returned rows -> Set new data
foreach ($queryData AS $key => $value)
{
$this->set($fieldToName[$key], (string)$value);
}
// Success
return true;
}
catch (Exception $e)
{
$this->error('Database Load Failed: Class: %s, ID: %s, Error: %s', array(get_class($this), $this->get('id'), $e->getMessage()));
}
// Fail
return false;
}
// Destroy
public function destroy($field = 'id')
{
try
{
// Error checking
if (!$this->isTableDefined())
{
throw new Exception('No Table defined for this class');
}
if (!$this->get($field))
{
throw new Exception(sprintf('Operation field not set: %s', strtoupper($field)));
}
// Variables
$fieldToName = array_flip($this->databaseFields);
// Query row data
$query = sprintf("DELETE FROM `%s` WHERE `%s`='%s'",
$this->db->sanitize($this->databaseTable),
$this->db->sanitize($this->databaseFields[$field]),
$this->db->sanitize($this->get($field))
);
// INFO
$this->info($query);
// Did we find a row in the database?
if (!$queryData = $this->db->query($query)->fetch()->get())
{
throw new Exception('Failed to delete');
}
// Success
return true;
}
catch (Exception $e)
{
$this->error('Database Destroy Failed: Class: %s, ID: %s, Error: %s', array(get_class($this), $this->get('id'), $e->getMessage()));
}
// Fail
return false;
}
// Error
public function error($txt, $data = array())
{
if ($this->debug)
{
$txt = (is_array($data) && count($data) ? vsprintf($txt, $data) : $txt);
$GLOBALS['FOGCore']->error(sprintf('Class: %s, Error: %s', get_class($this), $txt));
}
}
// Info
public function info($txt, $data = array())
{
if ($this->debug)
{
$txt = (is_array($data) && count($data) ? vsprintf($txt, $data) : $txt);
$GLOBALS['FOGCore']->info(sprintf('Class: %s, Info: %s', get_class($this), $txt));
}
}
// isValid
public function isValid()
{
// TODO: Add $this->databaseFieldsRequired checks
if ($this->get('id') || $this->get('name'))
{
return true;
}
return false;
}
// isTableDefined
private function isTableDefined()
{
return (!empty($this->databaseTable) ? true : false);
}
// Name is returned if class is printed
public function __toString()
{
return $this->get('name');
}
}