Location: PHPKode > projects > Recess PHP Framework > recess/recess/database/pdo/PdoDataSet.class.php
<?php
Library::import('recess.database.sql.SqlBuilder');
Library::import('recess.database.sql.ISqlSelectOptions');
Library::import('recess.database.sql.ISqlConditions');

/**
 * PdoDataSet is used as a proxy to query results that is realized once the results are
 * iterated over or accessed using array notation. Queries can thus be built incrementally
 * and an SQL request will only be issued once needed.
 *  
 * Example usage:
 * 
 * $results = new PdoDataSet(Databases::getDefault());
 * $results->from('tableName')->equal('someColumn', 'Hi')->limit(10)->offset(50);
 * foreach($results as $result) { // This is when the query is run!
 * 		print_r($result);
 * }
 * 
 * @author Kris Jordan <hide@address.com>
 * @copyright 2008, 2009 Kris Jordan
 * @package Recess PHP Framework
 * @license MIT
 * @link http://www.recessframework.org/
 */
class PdoDataSet implements Iterator, Countable, ArrayAccess, ISqlSelectOptions, ISqlConditions {
	
	/**
	 * The SqlBuilder instance we use to build up the query string.
	 *
	 * @var SqlBuilder
	 */
	protected $sqlBuilder;
	
	/**
	 * Whether this instance has fetched results or not.
	 *
	 * @var boolean
	 */
	protected $hasResults = false;
	
	/**
	 * Array of results that is filled once a query is realized.
	 *
	 * @var array of type $this->rowClass
	 */
	protected $results = array();
	
	/**
	 * The PdoDataSource which this PdoDataSet is extracted from.
	 *
	 * @var PdoDataSource
	 */
	protected $source;
	
	/**
	 * The Class which PDO will fetch rows into.
	 *
	 * @var string Classname
	 */
	public $rowClass = 'stdClass';
	
	/**
	 * Index counter for our location in the result set.
	 *
	 * @var integer
	 */
	protected $index = 0;
	
	/**
	 * @param PdoDataSource $source
	 */
	public function __construct(PdoDataSource $source) {
		$this->sqlBuilder = new SqlBuilder();
		$this->source = $source;
	}
	
	public function __clone() {
		$this->sqlBuilder = clone $this->sqlBuilder;
		$this->hasResults = false;
		$this->results = array();
		$this->index = 0;
	}
	
	protected function reset() {
		$this->hasResults = false;
		$this->index = 0;
	}
	
	/**
	 * Once results are needed this method executes the accumulated query
	 * on the data source.
	 */
	protected function realize() {  
		if(!$this->hasResults) {
			unset($this->results);
			$this->results = $this->source->queryForClass($this->sqlBuilder, $this->rowClass);
			$this->hasResults = true;
		}
	}
	
	/**
	 * Return the SQL representation of this PdoDataSet
	 *
	 * @return string
	 */
	public function toSql() {
		return $this->sqlBuilder->select();
	}
	
	/**
	 * Return the results as an array.
	 *
	 * @return array of type $this->rowClass
	 */
	public function toArray() {
		$this->realize();
		return $this->results;
	}
	
	public function count() {
		return iterator_count($this); 
	}
	
	
	/*
	 * The following methods are in accordance with the Iterator interface
	 */
	public function rewind() {
		if(!$this->hasResults) {$this->realize();}
		$this->index = 0;
	}
	
	public function current() {
		if(!$this->hasResults) {$this->realize();}
		return $this->results[$this->index];
	}

	public function key() {
		if(!$this->hasResults) {$this->realize();}
		return $this->index;
	}
	
	public function next() { 
		if(!$this->hasResults) {$this->realize();}
		$this->index++;
	} 
	
	public function valid() {
		if(!$this->hasResults) {$this->realize();}
		return isset($this->results[$this->index]);
	}
	
	/*
	 * The following methods are in accordance with the ArrayAccess interface
	 */
	function offsetExists($index) {
		if(!$this->hasResults) {$this->realize();}
		return isset($this->results[$index]);
	}

	function offsetGet($index) {
		if(!$this->hasResults) {$this->realize();}
		if(isset($this->results[$index])) {
			return $this->results[$index];
		} else {
			throw new OutOfBoundsException();
		}
	}

	function offsetSet($index, $value) {
		if(!$this->hasResults) {$this->realize();}
		$this->results[$index] = $value;
	}

	function offsetUnset($index) {
		if(!$this->hasResults) {$this->realize();}
		if(isset($this->results[$index])) {
			unset($this->results[$index]);
		}
	}
	
	function isEmpty() {
		return !(isset($this[0]) && $this[0] != null);
		// return !isset($this[0]);
	}
	
	/**
	 * Return the first item in the PdoDataSet or Null if none exist
	 *
	 * @return object or false
	 */
	function first() {
		if(!$this->hasResults) {
			$results = $this->range(0,1);
			if(!$results->isEmpty()) {
				return $results[0];
			}
		} else {
			if(!$this->isEmpty()) {
				return $this[0];
			}
		}
		
		return false;
	}
	
	/**
	 * @see SqlBuilder::assign
	 * @return PdoDataSet
	 */
	function assign($column, $value) { $copy = clone $this; $copy->sqlBuilder->assign($column, $value); return $copy; }
	
	/**
	 * @see SqlBuilder::useAssignmentsAsConditions
	 * @return PdoDataSet
	 */
	function useAssignmentsAsConditions($bool) { $copy = clone $this; $copy->sqlBuilder->useAssignmentsAsConditions($bool); return $copy; }
	
	/**
	 * @see SqlBuilder::from
	 * @return PdoDataSet
	 */
	function from($table) { $copy = clone $this; $copy->sqlBuilder->from($table); return $copy; }
	
	/**
	 * @see SqlBuilder::leftOuterJoin
	 * @return PdoDataSet
	 */
	function leftOuterJoin($table, $tablePrimaryKey, $fromTableForeignKey) { $copy = clone $this; $copy->sqlBuilder->leftOuterJoin($table, $tablePrimaryKey, $fromTableForeignKey); return $copy; }
	
	/**
	 * @see SqlBuilder::innerJoin
	 * @return PdoDataSet
	 */
	function innerJoin($table, $tablePrimaryKey, $fromTableForeignKey) { $copy = clone $this; $copy->sqlBuilder->innerJoin($table, $tablePrimaryKey, $fromTableForeignKey); return $copy; }
	
	/**
	 * @see SqlBuilder::selectAs
	 * @return PdoDataSet
	 */	
	function selectAs($select, $as) { $copy = clone $this; $copy->sqlBuilder->selectAs($select, $as); return $copy; }

	/**
	 * @see SqlBuilder::distinct
	 * @return PdoDataSet
	 */	
	function distinct() { $copy = clone $this; $copy->sqlBuilder->distinct(); return $copy; }

	/**
	 * @see SqlBuilder::equal
	 * @return PdoDataSet
	 */
	function equal($lhs, $rhs){ $copy = clone $this; $copy->sqlBuilder->equal($lhs,$rhs); return $copy; }

	/**
	 * @see SqlBuilder::notEqual
	 * @return PdoDataSet
	 */
	function notEqual($lhs, $rhs) { $copy = clone $this; $copy->sqlBuilder->notEqual($lhs,$rhs); return $copy; }

	/**
	 * @see SqlBuilder::between
	 * @return PdoDataSet
	 */	
	function between ($column, $lhs, $rhs) { $copy = clone $this; $copy->sqlBuilder->between($column, $lhs, $rhs); return $copy; }

	/**
	 * @see SqlBuilder::greaterThan
	 * @return PdoDataSet
	 */	
	function greaterThan($lhs, $rhs) { $copy = clone $this; $copy->sqlBuilder->greaterThan($lhs,$rhs); return $copy; }

	/**
	 * @see SqlBuilder::greaterThanOrEqualTo
	 * @return PdoDataSet
	 */	
	function greaterThanOrEqualTo($lhs, $rhs) { $copy = clone $this; $copy->sqlBuilder->greaterThanOrEqualTo($lhs,$rhs); return $copy; }

	/**
	 * @see SqlBuilder::lessThan
	 * @return PdoDataSet
	 */	
	function lessThan($lhs, $rhs) { $copy = clone $this; $copy->sqlBuilder->lessThan($lhs,$rhs); return $copy; }

	/**
	 * @see SqlBuilder::lessThanOrEqualTo
	 * @return PdoDataSet
	 */	
	function lessThanOrEqualTo($lhs, $rhs) { $copy = clone $this; $copy->sqlBuilder->lessThanOrEqualTo($lhs,$rhs); return $copy; }

	/**
	 * @see SqlBuilder::like
	 * @return PdoDataSet
	 */	
	function like($lhs, $rhs) { $copy = clone $this; $copy->sqlBuilder->like($lhs,$rhs); return $copy; }

	/**
	 * @see SqlBuilder::like
	 * @return PdoDataSet
	 */
	function notLike($lhs, $rhs) { $copy = clone $this; $copy->sqlBuilder->notLike($lhs,$rhs); return $copy; }
	
	/**
	 * @see SqlBuilder::isNull
	 * @return PdoDataSet
	 */	
	function isNull($lhs) { $copy = clone $this; $copy->sqlBuilder->isNull($lhs); return $copy; }

	/**
	 * @see SqlBuilder::like
	 * @return PdoDataSet
	 */
	function isNotNull($lhs) { $copy = clone $this; $copy->sqlBuilder->isNotNull($lhs); return $copy; }
	
	/**
	 * @see SqlBuilder::where
	 * @return PdoDataSet
	 */	
	function where($lhs, $rhs, $operator) { $copy = clone $this; $copy->sqlBuilder->where($lhs,$rhs,$operator); return $copy; }

	/**
	 * @see SqlBuilder::limit
	 * @return PdoDataSet
	 */	
	function limit($size) { $copy = clone $this; $copy->sqlBuilder->limit($size); return $copy; }

	/**
	 * @see SqlBuilder::offset
	 * @return PdoDataSet
	 */	
	function offset($offset) { $copy = clone $this; $copy->sqlBuilder->offset($offset); return $copy; }

	/**
	 * @see SqlBuilder::range
	 * @return PdoDataSet
	 */	
	function range($start, $finish) { $copy = clone $this; $copy->sqlBuilder->range($start,$finish); return $copy; }

	/**
	 * @see SqlBuilder::orderBy
	 * @return PdoDataSet
	 */	
	function orderBy($clause) { $copy = clone $this; $copy->sqlBuilder->orderBy($clause); return $copy; }
}
?>
Return current item: Recess PHP Framework