info about link
: Javascript : PHP Index : MySQL :
database array caching class
: Source : : Explanation : : Example : : Todo : : Feedback :

DbArray.php

Easy and flexible class for storing database data into cached arrays

Added: 2009-05-07 19:39:23

download

<?
/******
* You may use and/or modify this script as long as you:
* 1. Keep my name & webpage mentioned
* 2. Don't use it for commercial purposes
*
* If you want to use this script without complying to the rules above, please contact me first at: marty@excudo.net

* Author: Martijn Korse
* Website: http://devshed.excudo.net
*
* Date:  2009-05-07 19:39:23
***/


/**
 * The source shown here contains the code of 3 classes.
 * If you download the zip file, the source of these 3 classes will be split into three seperate files
 */

/***** DbArray.php *****/

require_once 'DbArray/Exception.php';

/**
 * Purpose of this class is to provide an easy interface for retrieving data from
 * the database and cache it as a php-array in a file on the server.
 * The class implements the singleton pattern.
 * It has three public functions which you can use:
 * 1. get(), for retrieving an Array
 * 2. exists(), for testing whether an array, or subvalues of the array, exists
 * 3. cache(), to write data to the cached files.
 *
 * For every array of data, you'll need to create a separate class that holds the
 * information about how to retrieve this data from the database and how to structure
 * it. Writing these classes is relatively simple as it comes with an abstract
 * class that provides almost all default values (which can be overriden)
 *
 * NOTE: this class assumes a database connection already exists!
 */
class DbArray
{
   
/*****
    * The following constants act as configuration.
    * Please modify them when installing this class
    ***/

   /**
    * When calling the static get method and the array has to be created, the class
    * with the query needs to be included. This constant is used for looking up that filename.
    * %s will be replaced with the $key argument with which get() was called
    */
   
const FILE_FORMAT         "db_%s.php";
   
/**
    * See above; The class-name within this file will have the format of this constant.
    * %s will be replaced with the $key argument with which get() was called
    */
   
const CLASS_FORMAT         "DbArray_Query_%s";
   
/**
    * When an array is loaded and is going to be written to a cache-file, the array
    * needs to have a name in that file. This is the format of that name.
    * %s will be replaced with the $key argument with which get() was called
    */
   
const ARRAY_FORMAT         "dbArray_%s";
   
/**
    * Path to the folder where the classes with the queries are stored. This is
    * relative to the root folder of you project and will therefor be combined
    * with the one below.
    * If null (the default), it will expect the class to be in ./DbArray/Query/
    * @see CLASS_DIR_ROOT
    */
   
const CLASS_DIR            null;
   
/**
    * Path to the root folder of your project
    * @see CLASS_DIR
    */
   
const CLASS_DIR_ROOT         $_SERVER['DOCUMENT_ROOT'];
   
/**
    * Path to the folder where the loaded arrays are stored (cached). This is
    * relative to the root folder of you project and will therefor be combined
    * with the one below.
    * @see CACHE_DIR_ROOT
    */
   
const CACHE_DIR            "tmp/array";
   
/**
    * Path to the root folder of your project
    * @see CACHE_DIR
    */
   
const CACHE_DIR_ROOT         $_SERVER['DOCUMENT_ROOT'];
   
/**
    * This value will be used for the chmod-command on the cached file, once the
    * array has been written to it.
    */
   
const CHMOD            0755;
   
/**
    * The newline that is used in the cached file.
    */
   
const NEWLINE            "\r\n";
   
/**
    * The name of the function we need to call in case an error has occured during
    * the getting of the array. It can also be the name of the method of a class:
    * in this case you'll also need to define CALLBACK_CLASS_IF_ERROR
    * @see reportError()
    */
   
const CALLBACK_METHOD_IF_ERROR      null;
   
/**
    * The name of the class which holds the method defined in CALLBACK_METHOD_IF_ERROR
    * @see CALLBACK_METHOD_IF_ERROR
    */
   
const CALLBACK_CLASS_IF_ERROR      null;

   
/**
    * Singleton instance
    *
    * @var DbArray
    */
   
protected static $_instance null;

   
/**
    * This array is used to store all the 'database arrays'
    *
    * @var array
    */
   
protected static $_data = array();

   
/**
    * This variable is used to toggle the behaviour of throwing exceptions from the get-method
    * Normally we don't want exceptions, but just an empty array (and the error logged). However, when
    * we are using the get-method internally, we do want to know about exceptions; in that case we quickly
    * switch on (set to True) this variable and then switch it back off (set to False) again once we're done.
    *
    * @var boolean
    */
   
protected static $_throwExceptions False;

   
/**
    * Singleton pattern implementation makes "new" unavailable
    *
    * @return void
    */
   
private function __construct()
   {}

   
/**
    * Singleton pattern implementation makes "clone" unavailable
    *
    * @return void
    */
   
private function __clone()
   {}

   
/**
    * creates a singleton instance
    *
    * @return DbArray
    */
   
public static function getInstance()
   {
      if (
null === self::$_instance)
      {
         
self::$_instance = new self();
      }

      return 
self::$_instance;
   }

   
/**
    * Retrieves an array.
    * When cache-file doesn't exist yet, it will be created.
    *
    * @param $key String   This is the key : 
    *             - by which the array is stored internally,
    *             - by which the array can be retrieved using this function
    *             - that is used in config constants FILE_FORMAT, CLASS_FORMAT
    *              & ARRAY_FORMAT and subsequent functions that make use of them
    * @param      NOTE: you can pass any number of parameters > 1 to this function.
    *            The first is explained above. The 2nd, 3rd, etc will be used to
    *            retrieve specific values in the array that is stored under $key. Example:
    *            - DbArray::get('categories', 1) will return $_data['categories'][1]
    *            - DbArray::get('categories', 2, 7) will return $_data['categories'][2][7]
    *
    * @return Array
    */
   
public static function get($key)
   {
      
$arguments func_get_args();
      if (
count($arguments) == 1)
      {
         if (
self::$_throwExceptions)
         {
            return 
self::getContent($key);
         }
         else
         {
            try {
               return 
self::getContent($key);
            } catch (
DbArray_Exception $exc) {
               
self::reportError("Exception: ".$exc->getMessage()." with DbArray, ".
                  
"line: ".$exc->getLine().", file: ".$exc->getFile().", ".
                  
"trace: ".$exc->getTraceAsString());
               return array();
            }
         }
      }
      elseif (
count($arguments) > 1)
      {
         
$arr self::get($key);
         
$returnArr $arr;
         for (
$x=1$x<count($arguments); $x++)
         {
            
$returnArr $returnArr[$arguments[$x]];
         }
         return 
$returnArr;
      }
   }

   
/**
    * Core that should have been part of the get() method, but has been isolated here
    * to allow for more flexible exception throwing. This way, depending on the value
    * of self::$_throwExceptions, get() can catch or deliberately not-catch any
    * exception that might be the result of this function call.
    * The value of self::$_throwExceptions is toggled by exists() before calling get()
    *
    * @param $key String   see get()
    *
    * @see   get()
    *
    * @return Array
    */
   
private static function getContent($key)
   {
      if (isset(
self::$_data[$key]))
      {
         return 
self::$_data[$key];
      }
      
// else
      
$cachedFilePath self::CACHE_DIR_ROOT."/".self::CACHE_DIR."/".sprintf(self::FILE_FORMAT$key);
      if (
file_exists($cachedFilePath))
      {
         require_once 
$cachedFilePath;
         
self::$_data[$key] = ${sprintf(self::ARRAY_FORMAT$key)};
         return 
self::$_data[$key];
      }
      
// else
      
self::$_data[$key] = self::getDbArray($key);
      if (
self::$_throwExceptions)
      {
         
self::write2cache($keyself::$_data[$key]);
      }
      else
      {
         try {
            
self::write2cache($keyself::$_data[$key]);
         } catch (
DbArray_Exception $exc) {
            
self::reportError("Exception: ".$exc->getMessage()." with DbArray, ".
               
"line: ".$exc->getLine().", file: ".$exc->getFile().", ".
               
"trace: ".$exc->getTraceAsString());
         }
      }
      return 
self::$_data[$key];
   }

   
/**
    * This method works similar to the native isset()
    * It requires at least 1 parameter, but can take any number of parameters.
    * It allows you to ask the class whether a database-array exists, or a key
    * within the database-array.
    *
    * @param $key String   This is the key by which the array should be stored
    *                  internally (in self::$_data)
    * @param      NOTE: you can pass any number of parameters > 1 to this function.
    *               The first is explained above. The 2nd, 3rd, etc will
    *               be used to test specific values in the array that is stored under $key. Example:
    *               - DbArray::exists('categories', 1) will test if $_data['categories'][1] exists
    *               - DbArray::exists('categories', 2, 7) will test if $_data['categories'][2][7] exists
    * 
    * @return Boolean
    */
   
public static function exists($key)
   {
      
$arguments func_get_args();
      if (
count($arguments) > 1)
      {
         try {
            
self::$_throwExceptions True;
            
$arr self::get($key);
            
self::$_throwExceptions False;
         } catch (
DbArray_Exception $e) {
            
self::$_throwExceptions False;
            if (
$e->getCode() == DbArray_Exception::PATH_INVALID_CODE)
            {
               return 
False;
            }
            else
            {
               throw new 
DbArray_Excpetion($e->getMessage()." in ".$e->getFile()." ".
                  
"on line ".$e->getLine(), $e->getCode());
            }
         }
         
$returnArr $arr;
         for (
$x=1$x<count($arguments); $x++)
         {
            if (!isset(
$returnArr[$arguments[$x]]))
            {
               return 
False;
            }
            else
            {
               
$returnArr $returnArr[$arguments[$x]];
            }
         }
         return 
True;
      }
      else
      {
         
trigger_error("Missing argument 2 for ".__CLASS__."::".__METHOD__."()"E_USER_WARNING);
      }
   }

   
/**
    * Writes an array to a cache-file, given the key
    * Using this key, the array will first be retrieved from the database and
    * then written to the cache
    *
    * @param $key String   See explanation under get()
    * 
    * @throws DbArray_Exception
    * 
    * @see getDbArray()
    * @see write2cache()
    * 
    * @return void
    */
   
public static function cache($key)
   {
      
self::write2cache($keyself::getDbArray($key));
   }

   
/**
    * Writes an array to a cache-file.
    * 
    * @param $key String   See explanation under get()
    * @param $arr Array   The array that we want to cache
    * 
    * @throws DbArray_Exception
    *
    * @return void
    */
   
protected static function write2cache($key$arr)
   {
      
$fullCacheDir   self::getFullCachePath();
      
$cacheDir   self::sanitizePath(self::CACHE_DIR);
      
$cacheDirRoot   self::sanitizePath(self::CACHE_DIR_ROOT);

      if (!
file_exists($fullCacheDir) || !is_dir($fullCacheDir))
      {         
         if (
strpos($cacheDirDIRECTORY_SEPARATOR) !== False)
         {
            
$parts explode(DIRECTORY_SEPARATOR$cacheDir);
         }
         else
         {
            
$parts = array($cacheDir);
         }
         
$partPath $cacheDirRoot;
         foreach (
$parts AS $part)
         {
            
$partPath .= DIRECTORY_SEPARATOR.$part;
            if (!
file_exists($partPath) || !is_dir($partPath))
            {
               if (@!
mkdir($partPathself::CHMOD))
               {
                  throw new 
DbArray_Exception(
                     
sprintf(DbArray_Exception::PATH_COULDNT_CREATE_MSG$partPath),
                     
DbArray_Exception::PATH_COULDNT_CREATE_CODE);
               }
            }
         }
      }
      
$fullPath $fullCacheDir.DIRECTORY_SEPARATOR.sprintf(self::FILE_FORMAT$key);
      if (
is_null($arr))
      {
         if (!isset(
self::$_data[$key]))
         {
            throw new 
DbArray_Exception(
               
sprintf(DbArray_Exception::NO_ARRAY_PASSED_MSG__CLASS____METHOD__$key),
               
DbArray_Exception::NO_ARRAY_PASSED_CODE);
         }
         
$arr self::$_data[$key];
      }
      if (
$fp fopen($fullPath"w"))
      {
         if (@!
fputs($fpself::arr2text($key$arr)))
         {
            throw new 
DbArray_Exception(
               
sprintf(DbArray_Exception::PATH_COULDNT_WRITE_MSG$fullPath),
               
DbArray_Exception::PATH_COULDNT_WRITE_CODE);
         }
         
fclose($fp);
      }
      else
      {
         throw new 
DbArray_Exception(
            
sprintf(DbArray_Exception::PATH_COULDNT_OPEN_MSG$fullPath),
            
DbArray_Exception::PATH_COULDNT_OPEN_CODE);
      }
   }

   
/**
    * Recursive function that converts an array to a string of PHP code that can
    * create that string. Including the PHP opening and closing tag
    * 
    * @param $key String      See get() for explanation
    * @param $arr Array      The array we want to parse. When recursing, this will be a sup-array
    * @param $depth Integer   Used during recursion to keep track of how deep we are in the array (sub-array-wise)
    * 
    * @return String
    */
   
protected static function arr2text($key$arr$depth 0)
   {
      
$x 0;
      
$indent "";
      while (
$x <= $depth)
      {
         
$indent .= "\t";
         
$x++;
      }

      if (
$depth == 0)
      {
         
$text "<?php".self::NEWLINE."\$".sprintf(self::ARRAY_FORMAT$key)." = array(".self::NEWLINE;
      }

      foreach (
$arr AS $k => $v)
      {
         if (!
is_int($k))
         {
            
$k "\"".str_replace('"''\"'$k)."\"";
         }
         if (
is_array($v))
         {
            
$text .= $indent.$k." => array(".self::NEWLINE;
            
$text .= self::arr2text($key$v, ($depth+1));
            
$text .= $indent."\t),".self::NEWLINE;
         }
         else
         {
            if (
is_bool($v))
            {
               
$v $v "true" "false";
               
$text .= $indent.$k." => ".$v.",".self::NEWLINE;
            }
            else
            {
               
$v str_replace('"''\"'$v);
               
$text .= $indent.$k." => \"".$v."\",".self::NEWLINE;
            }
         }
      }
      
      if (
$depth == 0)
      {
         
$text .= $indent.");".self::NEWLINE."?>";
      }
      return 
$text;
   }

   
/**
    * Retrieves data from a database as an array and returns it
    *
    * @param $key String   See explanation under get()
    *
    * @see createArray()
    *
    * @return Array
    */
   
protected static function getDbArray($key)
   {
      if (!
is_null(self::CLASS_DIR))
         
$file   self::CLASS_DIR_ROOT.DIRECTORY_SEPARATOR.self::CLASS_DIR.DIRECTORY_SEPARATOR.sprintf(self::FILE_FORMAT$key);
      else
         
$file   dirname(realpath(__FILE__)).DIRECTORY_SEPARATOR."DbArray".DIRECTORY_SEPARATOR."Query".DIRECTORY_SEPARATOR.sprintf(self::FILE_FORMAT$key);
      
$class   sprintf(self::CLASS_FORMAT$key);
      if (
file_exists($file))
      {
         require_once 
$file;
         
$obj = new $class;
         return 
self::createArray($obj);
      }
      else
      {
         throw new 
DbArray_Exception(
            
sprintf(DbArray_Exception::PATH_INVALID_MSG$file$key),
            
DbArray_Exception::PATH_INVALID_CODE
         
);
      }
   }

   
/**
    * This function holds all the logic for creating the array, based on the
    * DbArray_Query object that is passed to it.
    * If a callback function has been defined in the object, it will be
    * called before returning the constructed array
    *
    * @param $obj DbArray_Query_Abstract   Object that holds the query and configuration for the final array
    *
    * @throws DbArray_Exception
    * 
    * @return Array
    */
   
protected static function createArray(DbArray_Query_Abstract &$obj)
   {
      
// creating the first option of the array (or not)
      
if (False === $obj->getFirstOption())
      {
         
$outputArr = array();
      }
      elseif (
is_array($obj->getFirstOption()))
      {
         
$outputArr $obj->getFirstOption();
      }
      else
      {
         
$outputArr = array("" => $obj->getFirstOption());
      }
      
$firstOption $outputArr;

      
// getting the records from the database as array
      
$records self::getDbData($obj);

      
// if nothing was found, then act accordingly
      
if (count($records) == 0)
      {
         return 
$obj->getIfNoResults();
      }

      
// there were records, so we're gonna construct the array
      
foreach ($records AS $rowAss)
      {
         
// values of the current record
         
$row array_values($rowAss);
         
// mapper of the assoc-keys to numerical indexes
         
$rowMap array_keys($rowAss);

         
// total values, which corresponds to the amount of fields in the select query
         
$totalValues count($row);
         switch (
$totalValues)
         {
            
// if there was only one field, we give the key the same value as the corresponding value
            
case :
               
$row[1] = $row[0];
               
// break omitted
            // we add it to the output-array (but only if this key doesn't match the key of the first-option)
            
case :
               if (!
array_key_exists($row[0], $firstOption))
                  
$outputArr[$row[0]] = $row[1];
               break;
            default :
               
// 3 or more fields. we're gonna loop through them and construct the array
               
if (!array_key_exists($row[0], $firstOption))
               {
                  
// creating a reference to the output array.
                  // we will update this reference to the current subarray while we loop
                  
$tempArr =& $outputArr;
                  for (
$x=0$x<$totalValues$x++)
                  {
                     if (
False === $obj->getDepth() || $x $obj->getDepth())
                     {
                        if (!isset(
$tempArr[$row[$x]]))
                           
$tempArr[$row[$x]] = array();
                        if (
$x == $totalValues-2)
                        {
                           
// we construct the last leave
                           
$tempArr[$row[($totalValues-2)]] = $row[($totalValues-1)];
                           break;
                        }
                        else
                        {
                           
// updating reference with new sub-array
                           
$tempArr =& $tempArr[$row[$x]];
                        }
                     }
                     elseif (
False !== $obj->getDepth())
                     {
                        
$tempArr[$rowMap[$x]] = $rowAss[$rowMap[$x]];
                     }
                  }
               }
               break;
         }      
      }
      if (
method_exists($obj"callbackConvert"))
      {
         
// we update our array with some callback intelligence that has been defined.
         
$obj->callBackConvert($outputArr);
      }
      return 
$outputArr;
   }

   
/**
    * Execute (select) query on a database and return data
    * 
    * @param $obj DbArray_Query_Abstract   Object that holds the query
    *
    * @throws DbArray_Exception
    *
    * @return Array
    */
   
protected static function getDbData(DbArray_Query_Abstract &$obj)
   {
      switch (
$obj->getDbType())
      {
         case 
"PostgreSQL" :
            return 
self::getDbDataFromPostgresql($obj);
            break;
         case 
"MySQL" :
         default :
            return 
self::getDbDataFromMysql($obj);
      }
   }

   
/**
    * Execute query on mysql database
    * 
    * @param $obj DbArray_Query_Abstract
    *
    * @throws DbArray_Exception
    * 
    * @see getDbData()
    *
    * @return Array
    */
   
protected static function getDbDataFromMysql(DbArray_Query_Abstract &$obj)
   {
      
$records = array();
      if (!
$result mysql_query($obj->getQuery()))
      {
         throw new 
DbArray_Exception(mysql_error()." on line ".__LINE__." in ".__FILE__MYSQL_ERROR_CODE);
      }
      else
      {
         if (
mysql_num_rows($result) > 0)
         {
            while (
$rowAss mysql_fetch_assoc($result))
            {
               
$records[] = $rowAss;
            }
         }
      }
      return 
$records;
   }

   
/**
    * Execute query on postgresql database
    * 
    * @param $obj DbArray_Query_Abstract
    *
    * @throws DbArray_Exception
    * 
    * @see getDbData()
    *
    * @return Array
    */
   
protected static function getDbDataFromPostgresql(DbArray_Query_Abstract &$obj)
   {
      
$records = array();
      if (!
$result pg_query($obj->getQuery()))
      {
         throw new 
DbArray_Exception(mysql_error()." on line ".__LINE__." in ".__FILE__POSTGRESQL_ERROR_CODE);
      }
      else
      {
         if (
pg_num_rows($result) > 0)
         {
            while (
$rowAss pg_fetch_assoc($result))
            {
               
$records[] = $rowAss;
            }
         }
      }
      return 
$records;
   }

   
/**
    * Makes it easy to get the full path to the cache-dir quickly in a uniform way
    *
    * @see sanitizePath()
    *
    * @return String   The full path to the cache-directory
    */
   
public static function getFullCachePath()
   {
      
// creating full path to cache dir
      
return self::sanitizePath(self::CACHE_DIR_ROOT).DIRECTORY_SEPARATOR.self::sanitizePath(self::CACHE_DIR);
   }

   
/**
    * Sanitizes (part of) a certain path. By sanitizing we mean:
    * 1. convert all directory seperators that are non-native for the current OS to native ones
    *    (in other words, converting them into php's DIRECTORY_SEPARATOR constant)
    * 2. removing any trailing (back)slashes
    * Example: on windows environment temp/array/ will be converted to temp\array
    *
    * @param String $path   The (part of the) path we want to sanitize
    *
    * @return String
    */
   
public static function sanitizePath($path)
   {
      
// sanitizing directory separator
      
$contraSeparator DIRECTORY_SEPARATOR == '/' '\\' '/';
      
$newPath str_replace($contraSeparatorDIRECTORY_SEPARATOR$path);

      
// removing unwanted separators at the end
      
if (substr($newPath, -1) == DIRECTORY_SEPARATOR)
      {
         
$newPath substr($newPath0, -1);
      }
      return 
$newPath;
   }

   
/**
    * This class can warn the developer of errors at a few points in the code.
    * This function uses a user defined function/method to warn the developer of the error.
    * This function/method can be defined using the constants self::CALLBACK_METHOD_IF_ERROR
    * and possibly CALLBACK_CLASS_IF_ERROR. When both are null, the error will be
    * sent through trigger_error as an E_USER_WARNING.
    *
    * @param String $str   String with information about the error that occured
    *
    * @see CALLBACK_METHOD_IF_ERROR
    * @see CALLBACK_CLASS_IF_ERROR
    *
    * @return void
    */
   
protected static function reportError($str)
   {
      if (!
is_null(self::CALLBACK_CLASS_IF_ERROR))
      {
         
call_user_func(array(self::CALLBACK_CLASS_IF_ERRORself::CALLBACK_METHOD_IF_ERROR), $str);
      }
      elseif (!
is_null(self::CALLBACK_METHOD_IF_ERROR))
      {
         
call_user_func(self::CALLBACK_METHOD_IF_ERROR$str);
      }
      else
      {
         
trigger_error($strE_USER_WARNING);
      }
   }
}



/***** DbArray/Exception.php *****/

/**
 * Exception class that is used in DbArray.
 */
class DbArray_Exception extends Exception
{
   
/**
    * This one is thrown when the path to the file that should hold the
    * DbArray_Query_[...] class appears not to exist.
    */
   
const   PATH_INVALID_CODE      101;
   const   
PATH_INVALID_MSG      "The path [%s] doesn't exist. [%s] couldn't be resolved";

   
/**
    * This one is thrown when the cache-file couldn't be created
    */
   
const   PATH_COULDNT_CREATE_CODE   102;
   const   
PATH_COULDNT_CREATE_MSG      "Couldn't create path [%s]";

   
/**
    * This one is thrown when the cache-file exists, but couldn't be opened
    */
   
const   PATH_COULDNT_OPEN_CODE      103;
   const   
PATH_COULDNT_OPEN_MSG      "Couldn't open path [%s]";

   
/**
    * This one is thrown when the cache-file exists but we can't write to it
    */
   
const   PATH_COULDNT_WRITE_CODE      104;
   const   
PATH_COULDNT_WRITE_MSG      "Coulnd't write to [%s]";

   
/**
    * This one is thrown when we want to write something to the cache. This can
    * be done by passing the Array directly or by providing a String that is
    * the key to an internal data-array. When a String is passed, but the
    * internal data array couldn't be found, this exception is thrown
    */
   
const   NO_ARRAY_PASSED_CODE      111;
   const   
NO_ARRAY_PASSED_MSG      "No array was passed to %s::%s and [%s] doesn't exist";

   
/**
    * Some errors that indicate a database error (any kind)
    */
   
const   DB_ERROR_CODE         120;
   const   
MYSQL_ERROR_CODE      121;
   const   
POSTGRESQL_ERROR_CODE      122;
}



/***** DbArray/Query/Abstract.php *****/

/**
 * This Abstract class has to be used when creating classes that can be used by
 * DbArray for retrieving data from the database The only function you 'have to'
 * write an implementation for is getQuery, which should return the database
 * query (as a string) that selects the data. The others act as defaults, but
 * can be overriden.
 */
abstract class DbArray_Query_Abstract
{
   
/**
    * Select what type of database you are using by modifying the value of this constant.
    * Valid values:
    * - MySQL
    * - PostgreSQL
    *
    * If you wish to add support for other database, please make the following modifications:
    * - add a protected function 'getDbDataFrom...'
    * - update the switch statement in getDbData() to use this function with the right value of DB_TYPE
    */
   
const DB_TYPE_MYSQL      "MySQL";
   const 
DB_TYPE_POSTGRESQL   "PostgreSQL";

   
/**
    * This function should return a database query, which selects the data that
    * should be cached as an array.
    *
    * @return String
    */
   
abstract public function getQuery();

   
/***********
    * Override the following functions in your implementation of this abstract
    * class, to change the behaviour of that particular data:
    *
    * - getFirstOption()
    * - getIfNoResults()
    * - getDepth()
    *
    * Note: If a lot of your implementation need the same behaviour, it might
    * be better to extend this Abstract class to some kind of (abstract) base
    * class which overrides one or more of these functions
    ****/

   /**
    * In some cases you'll want the first element of the array to be something
    * that is not in the database, for example when using the data for a
    * drop-down box where the first option displays something like
    * '- please select -'
    *
    * @return mixed,    boolean False   : means you don't want to use a first option
    *         String      : This string will be the first option value. an empty value
    *                    will be used as key (equivalent of (array("" => "value"))
    *         Array      : (a flat array with only 1 element) Same as String, but here
    *                    you'll be able to define your own key.
    */
   
public function getFirstOption()
   {
      return 
False;
   }

   
/**
    * This function will be called in case no database data was found.
    * It allows you to have control over what will be cached in this case.
    *
    * @return Array
    */
   
public function getIfNoResults()
   {
      return array();
   }

   
/**
    * This function allows you to control the 'depth' of the array. Normally,
    * the depth is determined by the amount of fields in the SELECT query:
    * - 2 fields will result in a flat array
    * - 3 fields in an array with max. 1 (sub)array per key -> this is one deep (depth = 1)
    * - 4 fields in an array with max. 2 (sub)array per key -> this is one deep (depth = 2)
    * etc.
    * By overriding this function you can modify this automatic behaviour and
    * limit the depth. Example:
    * query:
    *      SELECT groupId, contactId, name, age FROM ...
    * depth:
    *      2
    * array:
    *      array(
    *         1 => array(
    *            1 => array(
    *               "name"   => "some name",
    *               "age"   => "20",
    *               ),
    *            2 => array(
    *               "name"   => "some other name",
    *               "age"   => "30",
    *               ),
    *            ),
    *         2 => array(
    *            3 => array(
    *               "name"   => "yet another name",
    *               "age"   => "40",
    *               ),
    *            ),
    *         );
    *
    * @return Integer
    */
   
public function getDepth()
   {
      return 
False;
   }

   
/**
    * This determines from what kind of database the data is retrieved.
    * Either change the return value here, so the default will be different for
    * all your implementations, or change it in the implemented classes
    *
    * @return String
    */
   
public function getDbType()
   {
      return 
self::DB_TYPE_MYSQL;
   }
}
?>

download

=[Disclaimer]=     © 2005-2018 Excudo.net