changedProps)) { $newId = $this->saveToDb($this->id, $this->table, $this->changedProps); $this->changedProps = array(); } else return true; if ($this->id == 0 && $newId) { $this->updateId($newId); } return $this->id; } public function delete() { if ($this->id > 0) { $retVal = $this->deleteFromDb($this->id, $this->table) && $this->clearProperties($this->props); } else if ($this->id = 0) return true; return false; } private function updateId($id) { $this->id = $id; $this->props['id'] = $id; } private function saveToDb($id, $table, array $data) { $DB = DB::getInstance(); // DB is a singleton custom database wrapper if ($id == 0) { $sql = $this->prepSqlInsert($id, $table, $data); } else { $sql = $this->prepSqlUpdate($id, $table, $data); } return $DB->insert($sql); } private function prepSqlUpdate($id, $table, array $data) { $sql = "UPDATE " . $table ." SET "; foreach ($data as $key => $value) { if ($value == "") { $sql .= "$key = NULL,"; } else { $sql .= "$key = '" . addslashes($value) . "',"; } } $sql = self::chopLastComma($sql); $sql .= " WHERE id='$id';"; return $sql; } private function prepSqlInsert($id, $table, array $data) { $sql = "INSERT INTO " . $table ."("; foreach ($data as $key=>$value) { $sql .= "$key,"; } $sql = self::chopLastComma($sql); $sql .= ") VALUES ("; foreach ($data as $key => $value) { $sql .= "'" . addslashes($value) . "',"; } $sql = self::chopLastComma($sql); $sql .= ");"; return $sql; } private function deleteFromDb($id, $table) { $DB = DB::getInstance(); $sql = "DELETE FROM " . $this->table . " WHERE id='" . $this->id . "'"; return $DB->delete($sql); } private function clearProperties(array $properties) { foreach ($properties as $key=>$value) { $properties[$key] = ''; } return true; } /** Object[] getAllByCriteria(String $tableName, String $className, String[][] $criteria) * The intent of this method is to abstract the general nature of the query * SELECT * FROM $tableName WHERE $fieldName = $fieldValue * where $fieldName and $fieldValue are name-value pairs in $criteria. * This method returns an array of $className objects. **/ protected static function getAllByCriteria($tableName, $className, $criteria = array()) { $all = array(); $DB = DB::getInstance(); $sql = "SELECT * FROM " . $tableName; if (sizeof($criteria) != 0) { $sql .= " WHERE "; foreach($criteria as $key=>$value) { $sql .= $key . "='" . $value . "' AND "; } $sql = self::chopLastAnd($sql); } $result = $DB->select($sql); foreach ($result as $row) { $obj = new $className(); $obj->init($row); $all[] = $obj; } return $all; } protected static function getOneByCriteria($tableName, $className, $criteria = array()) { $DB = DB::getInstance(); $sql = "SELECT * FROM " . $tableName; if (sizeof($criteria) != 0) { $sql .= " WHERE "; foreach($criteria as $key=>$value) { $sql .= $key . "='" . $value . "' AND "; } $sql = self::chopLastAnd($sql); } $result = $DB->select($sql); if(sizeof($result)) { $obj = new $className(); $obj->init($result[0]); return $obj; } else { return false; } } public function __construct($idOrProperties, $table) { if (is_array($idOrProperties)) { // A very dangerous approach... but we like to live dangerously $this->id = $idOrProperties['id']; $this->table = $table; $this->init($idOrProperties); array_shift($idOrProperties); // remove id from list of changed properties (id is immutable) $this->changedProps = $idOrProperties; } else if ($idOrProperties >= 0) { $this->id = $idOrProperties; $this->table = $table; $this->init($this->getPropertiesFromDb($idOrProperties, $table)); } else throw new Exception('DAO constructor requires integer id or properties array'); } public function init(array $properties) { if (is_array($properties)) { $this->id = $properties['id']; $this->props = $properties; } else throw new Exception('DAO init() reqiures an array'); } private function getPropertiesFromDb($id, $table) { $DB = DB::getInstance(); if ($id) { $rs = $DB->select("SELECT * FROM " . $table . " WHERE id='" . $id . "';"); if (sizeof($rs) == 1) { return $rs[0]; } else return $this->getFieldsFromDb($id, $table); } else { return $this->getFieldsFromDb($id, $table); } } private function getFieldsFromDb($id, $table) { $DB = DB::getInstance(); $fields = $DB->getFields($table); $fields['id'] = $id; return $fields; } private function __get($propName) { if (array_key_exists($propName, $this->props)) { return $this->props[$propName]; } else if (method_exists($this, 'get' . $propName)) { return call_user_func(array($this, 'get' . $propName)); } else throw new Exception("Invalid property name \"$propName\"."); } private function __set($propName, $val) { if ($propName == 'id') { throw new Exception("Changing the id is not allowed."); } if (!array_key_exists($propName, $this->props)) { throw new Exception("Invalid property name \"$propName\"."); // XXX refactor to InvalidPropertyException } if ($this->props[$propName] == $val) { return; } else { $this->changedProps[$propName] = $val; $this->props[$propName] = $val; } } function __destroy() { $this->props = null; $this->changedProps = null; } public function __toString() { $s = __CLASS__ . ":"; foreach ($this->props as $key=>$value) { $s .= "$key=$value;"; } return $s; } private static function chopLastAnd($sql) { // used for sql string manipulation return substr($sql, 0, strlen($sql)-5); } private static function chopLastComma($sql) { // used for sql string manipulation return substr($sql,0,strlen($sql)-1); } } ?>