Source for file DataSource.php
Documentation is available at DataSource.php
* Base abstract class for data source drivers
* Copyright (c) 1997-2007, Andrew Nagy <asnagy@webitecture.org>,
* Olivier Guilyardi <olivier@samalyse.com>,
* Mark Wiesemann <wiesemann@php.net>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* CVS file id: $Id: DataSource.php,v 1.43 2007/11/01 11:13:16 olivierg Exp $
* @version $Revision: 1.43 $
* @package Structures_DataGrid
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* Base abstract class for DataSource drivers
* - fields: (array) Which data fields to fetch from the datasource.
* An empty array means: all fields.
* Form: array(field1, field2, ...)
* - primaryKey: (array) Name(s), or numerical index(es) of the
* field(s) which contain a unique record
* identifier (only use several fields in case
* of a multiple-fields primary key)
* - generate_columns: (bool) Generate Structures_DataGrid_Column objects
* with labels. See the 'labels' option.
* use Structures_DataGrid::generateColumns() instead
* - labels: (array) Data field to column label mapping. Only used
* when 'generate_columns' is true.
* Form: array(field => label, ...)
* use Structures_DataGrid::generateColumns() instead
* @author Olivier Guilyardi <olivier@samalyse.com>
* @author Andrew Nagy <asnagy@webitecture.org>
* @author Mark Wiesemann <wiesemann@php.net>
* @package Structures_DataGrid
* @version $Revision: 1.43 $
* Common and driver-specific options
* @see Structures_DataGrid_DataSource::_setOption()
* @see Structures_DataGrid_DataSource::addDefaultOptions()
* Special driver features
$this->_options = array ('generate_columns' => false ,
'multiSort' => false , // Multiple field sorting
'writeMode' => false , // insert, update and delete records
* Adds some default options.
* This method is meant to be called by drivers. It allows adding some
* @param array $options An associative array of the form:
* array(optionName => optionValue, ...)
* @see Structures_DataGrid_DataSource::_setOption
* Add special driver features
* This method is meant to be called by drivers. It allows specifying
* the special features that are supported by the current driver.
* @param array $features An associative array of the form:
* array(feature => true|false, ...)
* @param mixed $options An associative array of the form:
* array("option_name" => "option_value",...)
* @param string $name Option name
* @param mixed $value Option value
* Generate columns if options are properly set
* Note: must be called after fetch()
* @return array Array of Column objects. Empty array if irrelevant.
* @deprecated This method relates to the deprecated "generate_columns" option.
and $fieldList = $this->_options['fields']) {
include_once 'Structures/DataGrid/Column.php';
foreach ($fieldList as $field) {
// Begin driver method prototypes DocBook template
* This method is public, but please note that it is not intended to be
* called by user-space code. It is meant to be called by the main
* Structures_DataGrid class.
* It is an abstract method, part of the DataGrid Datasource driver
* interface, and must/may be overloaded by drivers.
* Fetching method prototype
* When overloaded this method must return an array of records.
* Each record can be either an associative array of field name/value
* pairs, or an object carrying fields as properties.
* This method must return a PEAR_Error object on failure.
* @param integer $offset Limit offset (starting from 0)
* @param integer $len Limit length
* @return object PEAR_Error with message
* "No data source driver loaded"
function &fetch($offset = 0 , $len = null )
return PEAR ::raiseError ("No data source driver loaded");
* Counting method prototype
* Note: must be called before fetch()
* When overloaded, this method must return the total number or records
* or a PEAR_Error object on failure
* @return object PEAR_Error with message
* "No data source driver loaded"
return PEAR ::raiseError ("No data source driver loaded");
* Sorting method prototype
* When overloaded this method must return true on success or a PEAR_Error
* Note: must be called before fetch()
* @param string $sortSpec If the driver supports the "multiSort"
* feature this can be either a single field
* (string), or a sort specification array of
* the form: array(field => direction, ...)
* If "multiSort" is not supported, then this
* @param string $sortDir Sort direction: 'ASC' or 'DESC'
* @return object PEAR_Error with message
* "No data source driver loaded"
function sort($sortSpec, $sortDir = null )
return PEAR ::raiseError ("No data source driver loaded");
* Datasource binding method prototype
* When overloaded this method must return true on success or a PEAR_Error
* @param mixed $container The datasource container
* @param array $options Binding options
* @return object PEAR_Error with message
* "No data source driver loaded"
function bind($container, $options = array ())
return PEAR ::raiseError ("No data source driver loaded");
* Record insertion method prototype
* Drivers that support the "writeMode" feature must implement this method.
* When overloaded this method must return true on success or a PEAR_Error
* @param array $data Associative array of the form:
* array(field => value, ..)
* @return object PEAR_Error with message
* "No data source driver loaded or write mode not
* supported by the current driver"
return PEAR ::raiseError ("No data source driver loaded or write mode not".
"supported by the current driver");
* Return the primary key specification
* This method always returns an array containing:
* - either one field name or index in case of a single-field key
* - or several field names or indexes in case of a multiple-fields key
* Drivers that support the "writeMode" feature should overload this method
* if the key can be detected. However, the detection must not override the
* @return array Field(s) name(s) or numerical index(es)
* Record updating method prototype
* Drivers that support the "writeMode" feature must implement this method.
* When overloaded this method must return true on success or a PEAR_Error
* @param array $key Unique record identifier
* @param array $data Associative array of the form:
* array(field => value, ..)
* @return object PEAR_Error with message
* "No data source driver loaded or write mode
* not supported by the current driver"
return PEAR ::raiseError ("No data source driver loaded or write mode not".
"supported by the current driver");
* Record deletion method prototype
* Drivers that support the "writeMode" feature must implement this method.
* When overloaded this method must return true on success or a PEAR_Error
* @param array $key Unique record identifier
* @return object PEAR_Error with message
* "No data source driver loaded or write mode
* not supported by the current driver"
return PEAR ::raiseError ("No data source driver loaded or write mode not".
"supported by the current driver");
* Resources cleanup method prototype
* This is where drivers should close sql connections, files, etc...
* List special driver features
* @return array Of the form: array(feature => true|false, etc...)
* Tell if the driver as a specific feature
* @param string $name Feature name
* Dump the data as returned by fetch().
* This method is meant for debugging purposes. It returns what fetch()
* would return to its DataGrid host as a nicely formatted console-style
* @param integer $offset Limit offset (starting from 0)
* @param integer $len Limit length
* @param string $sortField Field to sort by
* @param string $sortDir Sort direction: 'ASC' or 'DESC'
* @return string The table string, ready to be printed
* @uses Structures_DataGrid_DataSource::fetch()
function dump($offset=0 , $len=null , $sortField=null , $sortDir= 'ASC')
$records = & $this->fetch($offset, $len, $sortField, $sortDir);
if (!$columns and !$records) {
include_once 'Console/Table.php';
$table = new Console_Table ();
foreach ($columns as $col) {
$headers[] = is_null($col->fieldName )
: "{ $col->columnName } ({$col->fieldName })";
$table->setHeaders ($headers);
foreach ($records as $rec) {
return $table->getTable ();
* Base abstract class for SQL query based DataSource drivers
* - db_options: (array) Options for the created database object. This option
* is only used when the 'dsn' option is given.
* - count_query: (string) Query that calculates the number of rows. See below
* for more information about when such a count query
* @author Olivier Guilyardi <olivier@samalyse.com>
* @author Mark Wiesemann <wiesemann@php.net>
* @package Structures_DataGrid
* @version $Revision: 1.43 $
* Fields/directions to sort the data by
* Instantiated database object
* This property caches the result of count() to avoid running the same
* database query multiple times.
* @param string $query The query string
* @param mixed $options array('dbc' => [connection object])
* array('dsn' => [dsn string])
* @return mixed True on success, PEAR_Error on failure
function bind($query, $options = array ())
$this->_isConnection ($this->_options['dbc'])) {
} elseif (isset ($this->_options['dsn'])) {
$dbOptions = $options['db_options'];
$this->_handle = & $this->_connect ();
if (PEAR ::isError ($this->_handle)) {
return PEAR ::raiseError ('Could not create connection: ' .
$this->_handle->getMessage () . ', ' .
return PEAR ::raiseError ('No Database object or dsn string specified');
return PEAR ::raiseError ('Query parameter must be a string');
* @param integer $offset Offset (starting from 0)
* @param integer $limit Limit
* @return mixed The 2D Array of the records on success,
function &fetch($offset = 0 , $limit = null )
foreach ($this->_sortSpec as $field => $direction) {
$sortArray[] = $this->_quoteIdentifier ($field) . ' ' . $direction;
$sortString = join(', ', $sortArray);
// if we have a sort string, we need to add it to the query string
// if there is an existing ORDER BY statement, we can just add the
$query .= ', ' . $sortString;
} else { // otherwise we need to specify 'ORDER BY'
$query .= ' ORDER BY ' . $sortString;
//FIXME: What about SQL injection ?
$recordSet = $this->_getRecords ($query, $limit, $offset);
if (PEAR ::isError ($recordSet)) {
// Determine fields to render
* @return mixed The number or records (int),
// do we already have the cached number of records? (if yes, return it)
// try to fetch the number of records
if ($this->_options['count_query'] != '') {
// complex queries might require special queries to get the
$count = $this->_getOne ($this->_options['count_query']);
// $count has an integer value with number of rows or is a
// PEAR_Error instance on failure
// GROUP BY, DISTINCT, UNION and subqueries are special cases
// ==> use the normal query and then numRows()
$count = $this->_getRecordsNum ($this->_query);
if (PEAR ::isError ($count)) {
// don't query the whole table, just get the number of rows
$count = $this->_getOne ($query);
// $count has an integer value with number of rows or is a
// PEAR_Error instance on failure
// if we've got a number of records, save it to avoid running the same
if (!PEAR ::isError ($count)) {
* Disconnect from the database, if needed
* This can only be called prior to the fetch method.
* @param mixed $sortSpec A single field (string) to sort by, or a
* sort specification array of the form:
* array(field => direction, ...)
* @param string $sortDir Sort direction: 'ASC' or 'DESC'
* This is ignored if $sortDesc is an array
function sort($sortSpec, $sortDir = 'ASC')
/* vim: set expandtab tabstop=4 shiftwidth=4: */
Documentation generated on Tue, 18 Dec 2007 11:30:13 -0500 by phpDocumentor 1.4.0. PEAR Logo Copyright © PHP Group 2004.
|