query("SELECT custname FROM Customers WHERE custname LIKE 'bob'"); // 2. Optionally check if the query was executed ok. if (!$queryResult->isOk()){ trigger_error("Something completely wrong: " . $queryResult->error(), E_USER_ERROR); } // 3. Loop through the results. while ($row = $queryResult->fetchObject()){ echo "
" . $row->custname; } @version 1.5 @created 2003-10-01 @modified 2005-11-30 (added next() to ResultSet) @modified 2006-04-12 (added Record object, accessible via ResultSet next() and fetchRecord()) @modified 2006-04-19 (added offset and limit capabilities to ResultSet) @modified 2007-02-22 (added set() and has() to Record) @modified 2009-03-17 1.5 (added querySingle()) @requires php 4 */ class DataBase { var $host; var $user; var $passwd; var $database; var $persistent; var $conn = null; var $listeners; function DataBase($host = null, $user = null, $passwd = null, $database = null, $persistent = false, $openNow = true, $newLink = false){ global $DataBase_connections; $this->host = DataBase::getDefaultProperty('host', $host); $this->user = DataBase::getDefaultProperty('user', $user); $this->passwd = DataBase::getDefaultProperty('password', $passwd); $this->database = DataBase::getDefaultProperty('database', $database); $this->persistent = DataBase::getDefaultProperty('persistent', $persistent); $this->newLink = DataBase::getDefaultProperty('newLinkPerQuery', $newLink); $this->listeners = array(); if ($openNow){$this->open();} $DataBase_connections[count($DataBase_connections)] =& $this; } function getDefaultProperty($name, $defaultvalue = null){ global $DataBase_defaultSettings; if (isset($DataBase_defaultSettings[$name])){ return $DataBase_defaultSettings[$name]; }else{ return $defaultvalue; } } function setDefaultProperty($name, $value){ global $DataBase_defaultSettings; $DataBase_defaultSettings[$name] = $value; } /** Class method for getting an available, open connection. */ function &getConnection($host = null, $user = null, $passwd = null, $database = null){ global $DataBase_connections; $host = DataBase::getDefaultProperty('host', $host); $user = DataBase::getDefaultProperty('user', $user); $passwd = DataBase::getDefaultProperty('password', $passwd); $database = DataBase::getDefaultProperty('database', $database); $result = null; // Try to find a connection that has the same specifiers (host, user, database). // The $DataBase_connections array is filled by the DataBase constructor. for ($i=0; $ihost == $host && $conn->user == $user && $conn->database == $database){ return $conn; } } // If no similar connection was found, create a new one and put // it in the list for possible later use (which is done by the constructor itself). if ($result == null){ $result =& new DataBase($host, $user, $passwd, $database, false, true, true); } return $result; } /** Not implemented. Meant for when a connection pool is used. */ function returnConnection(&$connection){ } function open(){ if($this->persistent) { $this->conn = mysql_pconnect($this->host, $this->user, $this->passwd, $this->newLink); }else{ $this->conn = mysql_connect($this->host, $this->user, $this->passwd, $this->newLink); } if(!$this->conn){ trigger_error("DataBase->open(): Could not connect to database. " . mysql_error(), E_USER_ERROR); } if(@!mysql_select_db($this->database, $this->conn)){ $this->log("Could not select database: ". $this->database . " on " . $this->host . " (user ". $this->user . ").\n" . $this->error()); return false; } //Debug message // $this->log("open ". $this->host ." ". $this->user ." ". $this->database); return true; } function selectdb($db = "") { // echo "changing database to $db
"; if(!mysql_select_db($db, $this->conn)){return false;} else{$this->database = $db; return true;} } function close(){ $this->log("mysql_close" ." ". $this->host ." ". $this->user ." ". $this->database); return(@mysql_close($this->conn)); } function error(){ return (mysql_error()); } function &performQuery($query){ return new ResultSet($query, $this); } function &query($query, $offset = null, $limit = null){ if (!isset($this) || !is_a($this, 'DataBase')){$db =& Database::getConnection();} else{$db =& $this;} $result =& new ResultSet($query, $db, $offset, $limit); return $result; } function &querySingle($query, $offset = null, $rowType = null){ if (!isset($this) || !is_a($this, 'DataBase')){$db =& Database::getConnection();} else{$db =& $this;} $result =& $db->query($query, $offset, 1); if ($result->hasNext()){ $record =& $result->next($rowType); }else{ $record = null; } return $record; } /** This method is meant for queries that return only one value, like 'SELECT COUNT(custNo) FROM Customers'. Returns a ResultSet object with an extra property 'value', which contains the single result of the given query. If no value was returned by the database, the 'value' is set to null (for example if 'SELECT name FROM Customers WHERE id = 23' returns no name, because customer 23 does not exist). Example: $nrOfCustomers = DataBase::getValue("SELECT COUNT(custNo) FROM Customers"); if (!$nrOfCustomers->isOk()){trigger_error("Something went wrong: " . $nrOfCustomers->error());} echo("Number of customers: " . $nrOfCustomers->value); */ function getValue($query, $throwErrors = true){ if (!isset($this) || !is_a($this, 'DataBase')){$dbconn =& DataBase::getConnection();} else{$dbconn =& $this;} $result =& new ResultSet($query, $dbconn); if ($throwErrors && !$result->isOk()){trigger_error("DataBase->getValue(): Failed to get a value from the database, using query='$query'.\n" . $result->error(), E_USER_ERROR);} if ($result->numRows() == 0){ $result->value = null; }else{ $row = $result->fetchArray(); $result->value = $row[0]; } $result->freeResult(); return $result; } /** secureValue - Returns the string representation of the given value, to be used directly in an SQL query. In the cases of dates and strings, quotes are appended already, so you don't need to test for that on before hand. That's the point of this method. */ function secureValue($value){ if ($value == null){$value = "NULL";} else if (is_numeric($value)){$value = $value;} else {$value = "'" . DataBase::secureString($value) . "'";} return $value; } function secureColumn($name){ return "`" . preg_replace("/[`\\\\]/", "", $name) . "`"; } /** secureString - Escapes the backslashes and single quotes in the given string. */ function secureString($value){ $value = preg_replace("/\\\\/", "\\\\", $value); return preg_replace("/'/", "\\'", $value); } function getLastInsertedId(){ if (!isset($this) || !is_a($this, 'DataBase')){$dbconn =& DataBase::getConnection();} else{$dbconn =& $this;} return(@mysql_insert_id($dbconn->conn)); } function log($message, $alternateFilename = null){ global $DataBase_listeners; if (count($DataBase_listeners) == 0){ $this->addListener(new LogToDebug(), 'log'); } for ($i=0; $ilog($message, $alternateFilename); } } /** Add a listener voor the log() method (other events are not yet supported). Objects passed as log listeners should have a log() method themselves. */ function addListener(&$listener, $event = 'log'){ global $DataBase_listeners; $DataBase_listeners[] =& $listener; } } /** Default log handler. */ class LogToDebug { function log($message){ Debug::write($message); } } class ResultSet{ var $dbase = null; var $conn = null; var $result = null; var $rowType = null; var $keys = null; var $offset = null; var $limit = null; var $nextIndex = 0; var $maxIndex = 0; var $resultCount = 0; var $totalCount = 0; var $exceptionOnOutOfBounds = false; function ResultSet($query, &$dbase, $offset = null, $limit = null, $silent = true){ $this->dbase =& $dbase; $this->conn =& $dbase->conn; $this->rowType = DataBase::getDefaultProperty('rowType', 'object'); $this->exceptionOnOutOfBounds = !$silent; // Debug::write($query); $this->result = @mysql_query($query, $this->conn); if ($this->result == false){ $this->dbase->log($query . " " . mysql_error()); } // If it was a SELECT statement, check out how many rows there are // and store the results. if (preg_match('/^\s*SELECT/i', $query)){ // If offset and limit were given and the query itself contains // no limit statement, we have to do our own limiting. $this->totalCount = @mysql_num_rows($this->result); if ($offset !== null && $limit !== null && !preg_match('/FROM.+?LIMIT/i', $query)){ // Debug::write('Zelf limiten'); $this->nextIndex = $offset; $this->maxIndex = $offset + $limit - 1; if ($this->maxIndex >= $this->totalCount){$this->maxIndex = $this->totalCount - 1;} $this->resultCount = $this->maxIndex - $this->nextIndex + 1; @mysql_data_seek($this->result, $this->nextIndex); }else{ // Debug::write('MySql limit'); $this->nextIndex = 0; $this->maxIndex = $this->totalCount - 1; $this->resultCount = $this->totalCount; } // Debug::write('offset ' . $this->nextIndex . ' last index ' . $this->maxIndex); } } function isOk(){ return ($this->result != false); } function error(){ return (mysql_error($this->conn)); } function freeResult(){ return(@mysql_free_result($this->result)); } function affectedRows(){ return(@mysql_affected_rows($this->conn)); } function numFields() { return(@mysql_num_fields($this->result)); } /** keys - returns the columnnames in this result as an array. */ function keys(){ if ($this->keys == null){ $totalfields = mysql_num_fields($this->result); $this->keys = array(); for ($i=0; $i<$totalfields; $i++){ $this->keys[$i] = mysql_field_name($this->result, $i); } } return $this->keys; } function numRows(){ return(@mysql_num_rows($this->result)); } function count(){ return $this->resultCount; } function totalCount(){ return $this->totalCount; } function hasNext(){ return ($this->nextIndex <= $this->maxIndex); } function &next($rowType = null){ if ($this->nextIndex > $this->maxIndex){ if ($this->exceptionOnOutOfBounds){trigger_error("ResultSet->next(): ResultSet has no more elements.", E_USER_ERROR);} else {$record = null; return $record;} } if ($rowType == null){$rowType = $this->rowType;} $this->nextIndex++; if ($rowType == 'object'){ $record = @mysql_fetch_object($this->result); }else if ($rowType == 'record'){ $data = (@mysql_fetch_assoc($this->result)); if ($data != false){$record =& new Record($data, $this);} else {$record = null;} }else if ($rowType == 'associative'){ $record = @mysql_fetch_assoc($this->result); }else{ $record = @mysql_fetch_array($this->result); } return $record; } function &fetchRecord(){ return $this->next('record'); } function fetchObject(){ return $this->next('object'); } function fetchArray($resultType = MYSQL_NUM){ return $this->next('array'); } function fetchAssoc(){ return $this->next('associative'); } function getFieldName($nr){ return (@mysql_field_name($this->result, $nr)); } function getLastInsertedId(){ return (@mysql_insert_id($this->conn)); } function seek($rownumber){ return (@mysql_data_seek($this->result, $rownumber)); } } /** Record - Wrapper for a MySql record, with a get(fieldname) method. */ class Record { var $data; function Record (&$data, &$resultset){ $this->data =& $data; $this->resultset =& $resultset; } function get($name){ return $this->data[$name]; } function has($name){ return array_key_exists($name, $this->data); } function set($name, $value){ $this->data[$name] = $value; } function keys(){ return $this->resultset->keys(); } function &getAsArray(){ return $this->data; } } ?>plainFields = array( 'clientId'=>NULL, 'name'=>NULL, 'address'=>NULL, 'city'=>NULL, 'phone'=>NULL); // Call the parent contructor, which will automatically load // the data, if an id was given. parent::PersistentObject($id, $loadData); } } // Now test this class by getting a client by its clientId. $client =& new Client(2430); echo("Client: " . $client->get('name')); echo("Residence: " . $client->get('address') . ", " . $client->get('city')); // Change the phonenumber and directly store it in the database. $client->set('phone','020-5707200'); $client->store(); End of Example. Methods offered by PersistentObject Public: - getId - get, get an object field by name. - set, set the value of an object field. - validate, check all fields on validity (you'll have to write that yourself!). - isValid, checks if validate() renders any error codes, if any returns false, otherwise true. - store, store all fields in the database (whether it already exists or not). - loadDataFromArray, utility method to set all fields in one go. Protected: - getAllFields, returns an hashtable with all fields in the table for this class. - loadData, gets all fieldvalues from the database. - updateData, does an update on the database for this object (used by store()). - insertData, adds this object as a new row (used by store()). - loadReferencesFromArray @version 1.6 @created 2002-10-01 @modified 2005-12-02 Simplified @modified 2006-04-14 Added keys(), repaired bug in loadDataFromArray. @modified 2006-06-18 - Added abortStorageOnStorageError option (if false and something goes wrong in insertData(), updateData() or delete(), an error is added, using addError()). - Added addError(), getError() and getErrorMessage(). @modified 2006-04-13 Added backticks (`) around columnnames in the insert and update statements (got an error on a system with columnames like `password` and `privileges`). @modified 2009-11-10 Added storageManager interface. @requires DataBase-1.1.php */ class PersistentObject { // NOTE: The Object's fields/attributes are not to be accessed directly, but only // via the applicable methods. var $storageManager = null; // The database that contains the table of this object. Defaults to the constant MYSQL_DB. var $dbName = null; // The database table that contains all the objects of this type. var $dbTable = null; var $fullTableName = null; // The table field that corresponds to this object's id. var $idField = null; // The names of the plain (database) fields of the Ticket. By default // all database fields, except the reference fields. var $plainFields; // Contains any errors that have been encountered during any method execution // (especially the method validate() var $errorCodes; var $errorMessages; // Indicates if this object has been filled with data from the database already. var $loadedFromDatabase = false; // This field is used as a replacement for a real id in the database, if this // is a new object that is not yet associated with a record in the database. // After this object is actually stored (inserted), the id returned by getId() // will be the actual one from the database. Until then, tempId is returned. var $tempId; // var $abortStorageOnValidationError = true; var $abortStorageOnStorageError = true; /** Constructor. Loads its fields from the database if an id is given. */ function PersistentObject($id = NULL, $loadData = true, $storageManager = null){ // Initialize the variable object fields (can't be done above in the static initializer part, // since the arrays aren't static things, see the PHP documentation). if ($this->plainFields == NULL){$this->plainFields = array();} $this->errorCodes = array(); $this->errorMessages = array(); // Install the storage manager and get the actual table name for this entity. if ($storageManager == null){ $storageManager = new DefaultStorageManager($this->dbName); } $this->storageManager = $storageManager; $this->fullTableName = $this->storageManager->getFullTableName($this->dbTable); // Use our 'Class variable' to create a unique id. global $PersistentObjectCount; $tempIdPrefix = "temp_" . get_class($this) . "_"; if ($id != NULL && strpos($id, $tempIdPrefix) === 0){$this->tempId = $id;} else {$this->tempId = $tempIdPrefix . time() . "_" . ++$PersistentObjectCount;} if ($id == NULL){$id = $this->tempId;} if (is_null($this->idField) || $this->idField == null) {trigger_error("this->idField isn't avaiable", E_USER_ERROR);} $this->set($this->idField, $id); // Load the fields from the database, if requested. if ($id != $this->tempId && $loadData){$this->loadData();} } function getId(){ return $this->get($this->idField); } /** General getter method that returns the object field with the given name. Throws an error if the field does not exist. */ function get($fieldName){ if (array_key_exists($fieldName,$this->plainFields)){return $this->plainFields[$fieldName];} else{trigger_error("Can't 'get()' field '$fieldName', it does not exist in class '" . get_class($this) . "'", E_USER_ERROR);} } /** Tests if the given fieldname exists within this object. */ function has($fieldName){ return array_key_exists($fieldName,$this->plainFields); } /** General setter method that sets the value of the object field with the given name. Note: this doesn't store the value in the database, use storeData to commit any changes. Throws an error if the field does not exist yet: you can't increase the number of fields. */ function set($fieldName,$value){ if (array_key_exists($fieldName,$this->plainFields)){$this->plainFields[$fieldName] = $value;} else {trigger_error("Can't 'set()' field '$fieldName', it does not exist in class '" . get_class($this) . "'", E_USER_ERROR);} } function getError($errorCode){ $index = array_search($errorCode, $this->errorCodes); return array('code'=>$errorCode, 'message'=>$this->errorMessages[$index]); } function getErrorMessage($errorCode){ $index = array_search($errorCode, $this->errorCodes); return $this->errorMessages[$index]; } function addError($errorCode, $errorMessage = ''){ $this->errorCodes[] = $errorCode; $this->errorMessages[] = $errorMessage; } function hasErrors(){ return (count($this->errorCodes) > 0); } function hasError($errorCode, $errorCode2=null, $errorCode3=null){ if (in_array($errorCode, $this->errorCodes)){return true;} elseif ($errorCode2 != null && in_array($errorCode2, $this->errorCodes)){return true;} elseif ($errorCode3 != null && in_array($errorCode3, $this->errorCodes)){return true;} else {return false;} } function clearErrors(){ if (count($this->errorCodes) > 0){ $this->errorCodes = array(); $this->errorMessages = array(); } } function validate(){ // Validation code, filling up the $this->errorCodes array in case of any error. // Use $this->addError($code, $message) to add the errors. } function isValid($clearPreviousErrors = true){ if ($clearPreviousErrors){$this->clearErrors();} $this->validate(); return (count($this->errorCodes) == 0); } function isNew(){ $db =& $this->getDBConnection(); $exists = $db->getValue("SELECT COUNT(*) FROM " . $this->fullTableName . " WHERE " . $this->idField . " = '" . $this->getId() . "'"); return ($exists->value == 0); } /** Stores the object fields in the database. */ function store($abortOnError = true){ $this->abortStorageOnValidationError = $abortOnError; $this->abortStorageOnStorageError = $abortOnError; // First check if this object already exists (check on objectId) // If it exists: do an update // If not: do an insert. if ($this->isNew()){ $this->insertData(); }else{ $this->updateData(); } } function &createCopy(){ // Create a new object of this class and copy all db-fields (except // the id, but that is handled by loadDataFromArray already). eval('$copy =& new ' . get_class($this) . '();'); $copy->loadDataFromArray($this->getAllFields()); return $copy; } function delete($abortOnError = true){ $dbconn =& $this->getDBConnection(); $deleteStatement = "DELETE FROM " . $this->fullTableName . " WHERE " . $this->idField . "='" . $this->getId() . "'"; // Execute the statement and tell the object that its state is synchonous with the database. $result = $dbconn->query($deleteStatement); if (!$result->isOk()){ if ($abortOnError){trigger_error("Failed to delete " . get_class($this) . " '" . $this->getId() . "' from database.\n" . $result->error(), E_USER_ERROR);} else {$this->addError('DELETE_FAILED', $result->error());} }else{ $this->set($this->idField, $this->tempId); $this->loadedFromDatabase = false; } } function markDeleted() { // 'Removes' a row by setting the isDeleted property to 1. $dbase =& $this->getDBConnection(); $result = $dbase->query("UPDATE " . $this->fullTableName . " SET isDeleted = 1" . " WHERE " . $this->idField . " = " . $this->getId() ); if ($result->error()){trigger_error("Failed to set isDeleted to 1 for " . $this->fullTableName . " with id " . $this->getId() . ".\n" . $result->error(), E_USER_ERROR);} } /** Utility method for bulk-setting this object's fields from an array Throws an error when the given array is incomplete. REMIND: Maybe that's a bit heavy, but it is a quick way of detecting inconsequences in the dataflow. */ function loadDataFromArray($hash, $silent = false){ foreach ($this->plainFields as $name=>$value){ // The id is a special case, since we work with a temporary id before an // object is stored in the database. Don't ever change the id if this object // has been loaded from the database! if ($name == $this->idField){continue;} if (!$silent && !array_key_exists($name,$hash)){trigger_error(get_class($this) . "->loadDataFromArray(): Error loading data from Array: field '$name' is missing in the given array.", E_USER_ERROR);} else if (array_key_exists($name,$hash)){$this->plainFields[$name] = $hash[$name];} } $this->loadedFromDatabase = false; } //-------------------------------------------------------- // Protected Methods //-------------------------------------------------------- /** Returns a database connection with the correct database already selected. */ function &getDBConnection(){ return $this->storageManager->getConnection(); } /** Returns all fields as an associative array. */ function getAllFields(){ return $this->plainFields; } function keys(){ return array_keys($this->plainFields); } /** Loads the object fields from the database. After this, all data will be available via the get(fieldname) method. */ function loadData(){ $this->loadDataWhere($this->idField . " = '" . DataBase::secureValue($this->getId()) . "'"); } /** Loads the object fields from the database. After this, all data will be available via the get(fieldname) method. */ function loadDataWhere($where){ $dbconn =& $this->getDBConnection(); // Get all fields from the table as an associative array. // Since we use an associative array for storing the object fields, // we just copy it to our own 'fields' array. $result =& $dbconn->query("SELECT * FROM " . $this->fullTableName . " WHERE " . $where); if (!$result->isOk()){trigger_error("Failed to read " . get_class($this) . " (where='" . $where . "') from the database.\n" . $result->error(), E_USER_ERROR);} if ($result->numRows() == 0){trigger_error("loadDataWhere: Couldn't find data for " . get_class($this) . " (where='" . $where . "') in the database.\n" . $result->error(), E_USER_ERROR);} $row = $result->fetchAssoc(); $this->set($this->idField, $row[$this->idField]); $this->loadDataFromArray($row); $this->loadedFromDatabase = true; // Lighten up the database. $result->freeResult(); } /** Does an update on the database using the fields in this object. Throws an error if the data is not valid (calls the isValid() method), this is done before any database actions are taken. Throws an error in any case of database malfunction. */ function updateData(){ $dbconn =& $this->getDBConnection(); // If the data is not valid, throw an error. if (!$this->isValid() && $this->abortStorageOnValidationError){ trigger_error("Update on database table '" . $this->fullTableName . "' aborted, because the object data seems to be (partially) invalid. Class " . get_class($this) . " (id='" . $this->getId() . "'): " . join(", ", $this->errorCodes), E_USER_ERROR); } // Build up the UPDATE statement with "name='value', " parts that correspond // to all the object fields, except 'id' which is the only field we don't want // to update. REMIND: What to do with reference fields, pointing to other // objects in the database? $updateStatement = "UPDATE `" . $this->fullTableName . "` SET "; foreach ($this->getAllFields() as $name=>$value){ if ($name == $this->idField){continue;} $value = str_replace("'", "''", $value); if ($value == null){ $updateStatement .= "`$name` = NULL, "; } else{ $updateStatement .= "`$name` = '" . $value . "', "; } } // Remove the last comma and space. $updateStatement = substr($updateStatement,0,-2); $updateStatement .= " WHERE `" . $this->idField . "` = '" . $this->getId() . "'"; // Execute the statement. $result = $dbconn->query($updateStatement); if (!$result->isOk()){ if ($this->abortStorageOnStorageError){trigger_error("Failed to update the database with " . get_class($this) . " (id='" . $this->getId() . "').\nQuery: $updateStatement\n" . $result->error(), E_USER_ERROR);} else {$this->addError('STORAGE_FAILED', $result->error());} }else{ $this->loadedFromDatabase = true; } } /** Adds a new Ticket to the database. After succesful execution this object has the corresponding id. Throws an error in any case of database malfunction. Throws an error if the data is not valid (calls the isValid() method), this is done before any database actions are taken. */ function insertData(){ $dbconn =& $this->getDBConnection(); // If the data is not valid, throw an error. if (!$this->isValid() && $this->abortStorageOnValidationError){ trigger_error("Insert on database table '" . $this->fullTableName . "' aborted, because the object data seems to be (partially) invalid. Class " . get_class($this) . " (id='" . $this->getId() . "'): " . join(", ", $this->errorCodes), E_USER_ERROR); } // Build up the INSERT statement with "name='value', " parts that correspond // to all the object fields, except 'id' which is the only field we don't want // to update. REMIND: What to do with reference fields, pointing to other // objects in the database? $insertStatement = "INSERT INTO `" . $this->fullTableName . "` ("; $valuesPart = ") VALUES ("; foreach ($this->getAllFields() as $name=>$value){ if ($name == $this->idField && $value == $this->tempId){continue;} $value = str_replace("'", "''", $value); $insertStatement .= "`$name`, "; if ($value == null){ $valuesPart .= "NULL, "; } else{ $valuesPart .= "'" . $value . "', "; } } // Remove the last commas and spaces. $insertStatement = substr($insertStatement,0,-2); $valuesPart = substr($valuesPart,0,-2); $insertStatement .= $valuesPart . ")"; // Execute the statement, set this object's id to the newly generated/incremented // value and tell the object that its state is synchonous with the database. $result = $dbconn->query($insertStatement); if (!$result->isOk()){ if ($this->abortStorageOnStorageError){trigger_error("Failed to insert new " . get_class($this) . " into database.\n$insertStatement\n" . $result->error(), E_USER_ERROR);} else {$this->addError('STORAGE_FAILED', $result->error());} }else{ $this->set($this->idField, $dbconn->getLastInsertedId()); $this->loadedFromDatabase = true; } } } class DefaultStorageManager { var $dbName = null; function DefaultStorageManager ($dbName){ $this->dbName = $dbName; } public function &getConnection (){ return DataBase::getConnection(null, null, null, $this->dbName); } public function getFullTableName ($name){ return $name; } } ?>'year','month'=>'mon','mon'=>'mon','day'=>'mday','mday'=>'mday','wday'=>'wday','yday'=>'yday','yearday'=>'yday','hour'=>'hours','minute'=>'minutes','second'=>'seconds', 'weekday'=>'weekday', 'weekdayNr'=>'wday', 'weekdayName'=>'weekday'); $GLOBALS['Date.locale'] = 'en'; $GLOBALS['Date.dateTexts'] = array(); /** Utility class for date time functionality. It has some analogy with the Calender class from Java (like the set() and add() methods). @version 1.1.3 @modified 2006-04-16 Added locale functionality. @modified 2006-06-16 format() now accepts a string for $date. @modified 2009-03-13 fixed defined/isset mistake in getTexts() . @author Jan Willem Nienhuis / Brikkelt Webprogramming */ class Date { var $timeStamp; var $fields; var $changed = false; /** This constructor accepts multiple types of parameters, all meant to initialize the Date object to a certain time. - (), will use the current time. - (timestamp), like the one returned from time(). - (timestring), any time string that can be converted by strtotime(). - (Date object), will use the timestamp of the given Date object. - (year,month,day,hour,min,sec), will initialize to the given date parameters. It is also possible to just give the year, or year and month, or year, month and day, etc. */ function Date($timeStampOrYear = null,$month=null,$day=1,$hour=0,$min=0,$sec=0,$microsec=0){ if ($month != null){ $this->setDateTime($timeStampOrYear,$month,$day,$hour,$min,$sec,$microsec); }else{ if ($timeStampOrYear == null){$this->timeStamp = time();} else if (is_a($timeStampOrYear,"Date")){$this->timeStamp = $timeStampOrYear->getTime();} else if (!is_numeric($timeStampOrYear)){$this->timeStamp = strtotime($timeStampOrYear);} else{$this->timeStamp = $timeStampOrYear;} $this->fields = getdate($this->timeStamp); } // $this->fields['microseconds'] = $microsec; } function setDateTime($yearOrDateString,$month=1,$day=1,$hour=0,$min=0,$sec=0,$microsec=0){ if (!is_numeric($yearOrDateString)){ $this->setTime(strtotime($yearOrDateString)); }else{ if ($yearOrDateString != -1){$this->fields['year'] = $yearOrDateString;} if ($month != -1){$this->fields['mon'] = $month;} if ($day != -1){$this->fields['mday'] = $day;} if ($hour != -1){$this->fields['hours'] = $hour;} if ($min != -1){$this->fields['minutes'] = $min;} if ($sec != -1){$this->fields['seconds'] = $sec;} // $this->fields['microseconds'] = $microsec; $this->changed = true; } } function computeTime(){ $this->timeStamp = mktime($this->fields['hours'], $this->fields['minutes'], $this->fields['seconds'], $this->fields['mon'], $this->fields['mday'], $this->fields['year']); $this->fields = getdate($this->timeStamp); $this->changed = false; } function setTime($timeStamp){ $this->timeStamp = $timeStamp; $this->fields = getdate($this->timeStamp); $this->changed = false; } /** Returns this Date's UNIX timestamp. */ function getTime(){ if ($this->changed){$this->computeTime();} return $this->timeStamp; } /** Sets the given datefield with the given value. Possible fieldnames: - year - month - day - hour - minute - second */ function set($fieldname, $value){ $this->fields[$GLOBALS['Date.fieldnameMappingToPhp'][$fieldname]] = $value; $this->changed = true; } /** Changes this Date's timestamp, by adding the given value to the given field. To go back in time, supply a negative value. Possible fieldnames: - year - month - day - hour - minute - second */ function add($fieldname, $value){ $this->fields[$GLOBALS['Date.fieldnameMappingToPhp'][$fieldname]] += $value; $this->changed = true; } /** Possible fieldnames: - year - month - day - weekday - hour - minute - second */ function get($fieldname){ if ($this->changed){$this->computeTime();} return $this->fields[$GLOBALS['Date.fieldnameMappingToPhp'][$fieldname]]; } /** Class function. Returns the current time up to microseconds. */ function getMicroTime(){ list($usec, $sec) = explode(" ",microtime()); return ((float)$usec + (float)$sec); } /** format Formats the given date using the given format. The date should be the number of seconds since 1 jan 1970 (result of time()). If no date is given, the current time is used. Example: Date::format('ddd d MMMM yyyy, hh:mm', time()); yields: Fri 15 August 2003, 12:32 The names of days and months may be changed. The following formatcodes will be replaced by the corresponding figures: yyyy, the complete year yy, last 2 digits of year MMMM, the full month name MMM, the short month name MM, zero padded month number (Januari = 01) M, month number (Januari = 1) dddd, full day name ddd, short day name dd, zero padded day-in-month number d, day-in-month number hh, zero padded hours h, hour mm, zero padded minutes m, minute ss, zero padded seconds s, seconds @param format the desired format. @param date the date in seconds since 1970 (like the result of time()). @param locale the code representing the language to be used for monthnames and daynames. Defaults to the value set with Date::setLocale() which defaults to 'en' on its term. */ function format ($format, $date = null, $locale = null){ if ($date == null && (!isset($this) || !is_a($this, 'Date'))){$date = time();} else if ($date == null && isset($this) && is_a($this, 'Date')){$date = $this->getTime();} else if (!is_numeric($date)){$date = strtotime($date);} $texts = Date::getTexts($locale); $datefields = getdate($date); $result = $format; $result = str_replace('yyyy', $datefields['year'], $result); $result = str_replace('yy', substr($datefields['year'], 2, 2), $result); $result = str_replace('MMMM', 'XX_XXXX_XX', $result); $result = str_replace('MMM', 'XX_XXX_XX', $result); $result = str_replace('MM', str_pad($datefields['mon'], 2, '0', STR_PAD_LEFT), $result); $result = str_replace('M', $datefields['mon'], $result); $result = str_replace('dddd', 'XX_zzzz_XX', $result); $result = str_replace('ddd', 'XX_zzz_XX', $result); $result = str_replace('dd', str_pad($datefields['mday'], 2, '0', STR_PAD_LEFT), $result); $result = str_replace('d', $datefields['mday'], $result); $result = str_replace('hh', str_pad($datefields['hours'], 2, '0', STR_PAD_LEFT), $result); $result = str_replace('h', $datefields['hours'], $result); $result = str_replace('mm', str_pad($datefields['minutes'], 2, '0', STR_PAD_LEFT), $result); $result = str_replace('m', $datefields['minutes'], $result); $result = str_replace('ss', str_pad($datefields['seconds'], 2, '0', STR_PAD_LEFT), $result); $result = str_replace('s', $datefields['seconds'], $result); // These are at the bottom, to prevent any replacements of M, m // d, h, etc that may be in the month- and daynames. $result = str_replace('XX_XXXX_XX', $texts['monthNamesLong'][$datefields['mon']-1], $result); $result = str_replace('XX_XXX_XX', $texts['monthNamesShort'][$datefields['mon']-1], $result); $result = str_replace('XX_zzzz_XX', $texts['dayNamesLong'][$datefields['wday']], $result); $result = str_replace('XX_zzz_XX', $texts['dayNamesShort'][$datefields['wday']], $result); return $result; } function setLocale($locale){ $GLOBALS['Date.locale'] = $locale; } function getLocale(){ return $GLOBALS['Date.locale']; } function &getTexts($locale){ if ($locale == null){ $locale = Date::getLocale(); } if (!isset($GLOBALS['Date.dateTexts'][$locale])){ $GLOBALS['Date.dateTexts'][$locale] = array(); $texts =& $GLOBALS['Date.dateTexts'][$locale]; switch ($locale){ case 'nl': $texts['monthNamesLong'] = array('januari','februari','maart','april','mei','juni','juli','augustus','september','oktober','november','december'); $texts['monthNamesShort'] = array('jan','feb','maa','apr','mei','jun','jul','aug','sep','okt','nov','dec'); $texts['dayNamesLong'] = array('zondag','maandag','dinsdag','woensdag','donderdag','vrijdag','zaterdag'); $texts['dayNamesShort'] = array('zo','ma','di','wo','do','vr','za'); break; case 'en': default: // Fallback: english. $texts['monthNamesLong'] = array('january','february','march','april','may','june','july','august','september','oktober','november','december'); $texts['monthNamesShort'] = array('jan','feb','mar','apr','may','jun','jul','aug','sep','okt','nov','dec'); $texts['dayNamesLong'] = array('sunday','monday','tuesday','wednesday','thursday','friday','saturday'); $texts['dayNamesShort'] = array('sun','mon','tue','wed','thu','fri','sat'); break; } } return $GLOBALS['Date.dateTexts'][$locale]; } } ?>