Ferreteria/archive/data.php

From Woozle Writes Code
< Ferreteria‎ | archive
Revision as of 21:15, 30 August 2007 by htyp>Woozle (New page: <php><?php /* =========================== *** DATA UTILITY CLASSES *** (2007-05-20 Wzl) These classes have been designed to be db-engine agnostic, but I wasn't able to test against anyt...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

<php><?php /* ===========================

*** DATA UTILITY CLASSES ***

(2007-05-20 Wzl) These classes have been designed to be db-engine agnostic, but I wasn't able to test against anything other than MySQL nor was I able to implement the usage of the dbx_ functions, as the system that I was using didn't have them installed. (2007-08-30 Wzl) posting this version at http://htyp.org/User:Woozle/data.php

  • /

class clsDatabase {

 private $cntOpen;	// count of requests to keep db open
 private $strType;	// type of db (MySQL etc.)
 private $strUser;	// database user
 private $strPass;	// password
 private $strHost;	// host (database server domain-name or IP address)
 private $strName;	// database (schema) name
 private $Conn;	// connection object

// status

 private $strErr;	// latest error message
 public $sql;	// last SQL executed (or attempted)
 public function __construct($iConn) {
   CallEnter('clsDatabase('.get_class($iConn).')');
   $this->Init($iConn);
   CallExit('clsDatabase()');
 }
 public function Init($iConn) {

// $iConn format: type:user:pass@server/dbname

   CallEnter('clsDatabase.Init('.get_class($iConn).')');
   $this->cntOpen = 0;
   list($part1,$part2) = split('@',$iConn);
   list($this->strType,$this->strUser,$this->strPass) = split(':',$part1);
   list($this->strHost,$this->strName) = explode('/',$part2);
   $this->strType = strtolower($this->strType);	// make sure it is lowercased, for comparison
   CallExit('clsDatabase.Init()');
 }
 public function Open() {
   CallEnter('clsDatabase.Open()');
   if ($this->cntOpen == 0) {

// then actually open the db

     if ($this->strType == 'mysql') {
       $this->Conn = new mysqli($this->strHost,$this->strUser,$this->strPass,$this->strName);
     } else {
       $this->Conn = dbx_connect($this->strType,$this->strHost,$this->strName,$this->strUser,$this->strPass);
     }
   }
   $this->cntOpen++;
   CallExit('clsDatabase.Open() - '.$this->cntOpen.' lock'.Pluralize($this->cntOpen));
 }
 public function Shut() {
   CallEnter('clsDatabase.Shut()');
   $this->cntOpen--;
   if ($this->cntOpen == 0) {
     if ($this->strType == 'mysql') {
       $this->Conn->close();
     } else {
       dbx_close($this->Conn);
     }
   }
   CallExit('clsDatabase.Shut() - '.$this->cntOpen.' lock'.Pluralize($this->cntOpen));
 }
 public function _api_query($iSQL) {

// USAGE: should only be used by clsDataItem

   $this->sql = $iSQL;
   if ($this->strType == 'mysql') {
     $this->Conn->real_query($iSQL);
     return $this->Conn->store_result();
   } else {
     return dbx_query($this->Conn,$iSQL,DBX_RESULT_ASSOC);
   }
 }
 public function Exec($iSQL) {

// MYSQL only

   CallEnter('clsDataTable_noID.Exec('.$iSQL.')');
   $this->sql = $iSQL;
   $objQry = $this->Conn->prepare($iSQL);
   if (is_object($objQry)) {
     $ok = $objQry->execute();
     if (!$ok) {
       $this->txtErr = $this->Conn->error;
     }
   } else {
     $ok = false;
     echo '
SQL error: '.$iSQL.'
'; } $objQry->close(); CallExit('clsDataTable_noID.Exec()'); return $ok; } public function NewID() { return $this->Conn->insert_id; } public function SafeParam($iString) { return $this->Conn->escape_string($iString); } public function ErrorText() { return $this->txtErr; }

}

class clsDataTable_noID {

 protected $objDB;	// clsDatabase
 protected $strName;
 public function __construct($iDB,$iName) {
   CallEnter('clsDataTable_noID('.get_class($iDB).','.$iName.')');
   $this->objDB = $iDB;
   $this->strName = $iName;
   $this->objDB->Open();
   assert (isset($this->objDB));
   CallExit('clsDataTable_noID()');
 }
 public function __destruct() {
   $this->objDB->Shut();
 }
 protected function _newItem() {
   CallStep('('.get_class($this).')clsDataTable_noID._newItem()');
   return new clsDataItem_noID($this);
 }
 public function DB() {
   CallStep('('.get_class($this).')clsDataTable.DB()');
   return $this->objDB;
 }
 public function Name() {
   return $this->strName;
 }
 public function GetData($iFilt,$iSort=) {
   CallEnter('clsDataTable.GetData(filt="'.$iFilt.'",sort="'.$iSort.'")');
   $sql = 'SELECT * FROM '.$this->strName.' WHERE ('.$iFilt.')';
     if ($iSort != ) {
     $sql .= ' ORDER BY '.$iSort;
   }
   CallStep('SQL = ['.$sql.']');
   $objItem = $this->_newItem();
   $objItem->Query($sql);
   CallExit('clsDataTable.GetData() -> '.get_class($objItem));
   return $objItem;
 }

} // // clsDataTable_noID with functions based on autonumbered ID field // class clsDataTable extends clsDataTable_noID {

 protected $strIDname;	// name of unique ID field
 public function __construct($iDB,$iName,$iIDname='ID') {
   CallEnter('clsDataTable('.get_class($iDB).','.$iName.')');
   parent::__construct($iDB,$iName);
   $this->strIDname = $iIDname;
   CallExit('clsDataTable()');
 }
 public function NameOfID() {
   return $this->strIDname;
 }
 protected function _newItem() {
   CallStep('('.get_class($this).')clsDataTable._newItem()');
   return new clsDataItem($this);
 }
 public function GetItem($iID) {
   CallEnter('('.get_class($this).')clsDataTable.GetItem('.$iID.')');
   $sql = 'SELECT * FROM '.$this->strName.' WHERE '.$this->strIDname.'="'.$iID.'"';
   CallStep('SQL = ['.$sql.']');

// $objQry = dbx_query($this->objDB,$sql,DBX_RESULT_ASSOC);

   $objItem = $this->_newItem();
   $objItem->Query($sql);

// $objItem->Eat($objQry);

   CallExit('clsDataTable.GetItem('.$iID.') -> '.get_class($objItem));
   return $objItem;
 }

}

class clsDataItem_noID {

 public $Res;		// result set
 public $Row;		// first (presumably the *only*) row data
 public $Table;	// clsDataTable object
 public function __construct($iTable=NULL) {
   CallEnter('clsDataItem_noID('.get_class($iTable).')');
   $this->Init($iTable);
   CallExit('clsDataItem_noID()');
 }
 public function Init($iTable=NULL) {
   CallEnter('('.get_class($this).')clsDataItem_noID.Init('.get_class($iTable).')');
   $this->Table = $iTable; 

// this works for mysql only: // fetch the first row of the results as an associative array: // $this->Row = $iResults->fetch_assoc();

   CallExit('clsDataItem_noID.Init()');
 }
 public function Query($iSQL) {
   CallEnter('('.get_class($this).')clsDataItem_noID.Query('.$iSQL.')');
   assert($this->Table);
   assert($this->Table->DB());
   $this->Res = $this->Table->DB()->_api_query($iSQL);

/*

   if ($this->strType == 'mysql') {
     $this->Conn()->real_query($iSQL);
     $this->Res = $this->Conn()->store_result();
   } else {
     $this->Res = dbx_query($this->Conn(),$iSQL,DBX_RESULT_ASSOC);
   }
  • /

// later, we might want a flag for *not* doing this automatically... maybe.

   $this->FirstRow();
   CallExit('clsDataTable_noID.Query()');
 }
 protected function LoadResults() {

// USAGE: Abstract

   CallStep('('.get_class($this).')clsDataItem_noID.LoadResults()');
 }
 public function GetValue($iName) {

// this works for mysql only

   CallEnter('clsDataTable_noID.GetValue('.$iName.')');

// DumpArray($this->Row);

   $val = $this->Row[$iName];
   CallExit('clsDataTable_noID.GetValue('.$iName.') -> ['.$val.']');
   return $val;
 }
 public function RowCount() {
   $cntRows = $this->Res->num_rows;
   CallStep('('.get_class($this).')clsDataItem_noID.RowCount() -> '.$cntRows);
   return $cntRows;
 }
 public function HasData() {
   return (is_array($this->Row));
 }
 private function FirstRow() {
   CallEnter('('.get_class($this).')clsDataItem_noID.FirstRow()');
   if (!is_null($this->Res)) {
     if ($this->RowCount()) {
       $this->NextRow();	// get the first row of data
     }
   }
   CallExit('('.get_class($this).')clsDataItem_noID.FirstRow()');
 }
 public function NextRow() {

// this works for mysql only: // fetch the NEXT row of the results as an associative array:

   $this->Row = $this->Res->fetch_assoc();
   if (is_array($this->Row)) {
     $this->LoadResults();
   }
 }

} // // clsDataItem with functions based on autonumbered ID field // class clsDataItem extends clsDataItem_noID {

 public $ID;
 protected $strIDname;	// name of unique ID field

//TO DO: set $strIDname at construct time; use it instead of hard-coded "ID" // or maybe clsTitleExt should descend from clsDataItem_noID? Or need clsTitleIttyp class instead?

 protected function LoadResults() {

// USAGE: Descendants do not have to call this function

   CallEnter('('.get_class($this).')clsDataItem.LoadResults()');
   assert($this->Table);
   assert($this->Table->NameOfID());
   $this->ID		= $this->GetValue($this->Table->NameOfID());
   assert($this->ID);
   if (!isset($this->ID)) {
     echo '
TABLE: ['.$this->Table->Name().'] ID name: ['.$this->Table->NameOfID().']
'; } CallExit('clsDataItem.LoadResults()'); }

}

/* ========================

*** UTILITY FUNCTIONS ***
  • /

function Pluralize($iQty,$iSingular=,$iPlural='s') { if ($iQty == 1) { return $iSingular; } else { return $iPlural; } } /* ========================

*** DEBUGGING FUNCTIONS ***
  • /

// these could later be expanded to create a call-path for errors, etc.

function CallEnter($iName) {

 global $intCallDepth, $debug;
 if (KDO_DEBUG_STACK) {
   $intCallDepth++;
   if (KDO_DEBUG_HTML) {
     $debug .= '
'.str_repeat('>> ',$intCallDepth).''.$iName.''; } else { $debug .= "\n\n".str_repeat('*',$intCallDepth).$iName; } if (KDO_DEBUG_IMMED) { echo $debug; $debug = ; } }

} function CallExit($iName) {

 global $intCallDepth, $debug;
 if (KDO_DEBUG_STACK) {
   $intCallDepth--;
   if (KDO_DEBUG_HTML) {
     $debug .= '
'.str_repeat('>> ',$intCallDepth).'<< '.$iName.''; } else { $debug .= "\n\n".str_repeat('*',$intCallDepth).'<'; } if (KDO_DEBUG_IMMED) { DoDebugStyle(); echo $debug; $debug = ; } }

} function CallStep($iName) {

 global $intCallDepth, $debug;
 if (KDO_DEBUG_STACK) {
   if (KDO_DEBUG_HTML) {
     $debug .= '
'.str_repeat('>> ',$intCallDepth).'++ '.$iName.''; } else { $debug .= "\n\n".str_repeat('*',$intCallDepth).'+'; } if (KDO_DEBUG_IMMED) { DoDebugStyle(); echo $debug; $debug = ; } }

} function DumpArray($iArr) {

 global $intCallDepth, $debug;
 if (KDO_DEBUG) {
   while (list($key, $val) = each($iArr)) {
     if (KS_DEBUG_HTML) {
       $debug .= '
'.str_repeat('-- ',$intCallDepth+1).''; $debug .= " $key => $val"; $debug .= ''; } else { $debug .= "/ $key => $val /"; } if (KDO_DEBUG_IMMED) { DoDebugStyle(); echo $debug; $debug = ; } } }

} function DumpValue($iName,$iVal) {

 global $intCallDepth, $debug;
 if (KDO_DEBUG) {
   if (KS_DEBUG_HTML) {
     $debug .= '
'.str_repeat('-- ',$intCallDepth+1); $debug .= " $iName: [$iVal]"; $debug .= ''; } else { $debug .= "/ $iName => $iVal /"; } if (KDO_DEBUG_IMMED) { DoDebugStyle(); echo $debug; $debug = ; } }

} function DoDebugStyle() {

 static $isStyleDone = false;
 if (!$isStyleDone) {
   echo '<style type="text/css"></style>';
   $isStyleDone = true;
 }

}

?></php>