Source for file Connection.php
Documentation is available at Connection.php
* $Id: Connection.php 2290 2007-08-29 21:57:46Z zYne $
* 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.
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
* A wrapper layer on top of PDO / Doctrine_Adapter
* Doctrine_Connection is the heart of any Doctrine based application.
* An easy to use, pluggable eventlistener architecture. Aspects such as
* logging, query profiling and caching can be easily implemented through
* the use of these listeners
* Creating an instance of Doctrine_Connection does not connect
* to database. Connecting to database is only invoked when actually needed
* (for example when query() is being called)
* Doctrine_Connection provides many convenience methods such as fetchAll(), fetchOne() etc.
* Higher level functionality such as schema importing, exporting, sequence handling etc.
* is divided into modules. For a full list of connection modules see
* Doctrine_Connection::$_modules
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @category Object Relational Mapping
* @link www.phpdoctrine.com
* @version $Revision: 2290 $
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (MDB2 library)
* @var $dbh the database handler
* @var array $tables an array containing all the initialized Doctrine_Table objects
* keys representing Doctrine_Table component names and values as Doctrine_Table objects
* @var string $driverName the name of this connection driver
* @var boolean $isConnected whether or not a connection has been established
* @var array $supported an array containing all features this driver supports,
* keys representing feature names and values as
* one of the following (true, false, 'emulated')
* @var array $pendingAttributes An array of pending attributes. When setting attributes
* no connection is needed. When connected all the pending
* attributes are passed to the underlying adapter (usually PDO) instance.
* @var array $modules an array containing all modules
* transaction Doctrine_Transaction driver, handles savepoint and transaction isolation abstraction
* expression Doctrine_Expression driver, handles expression abstraction
* dataDict Doctrine_DataDict driver, handles datatype abstraction
* export Doctrine_Export driver, handles db structure modification abstraction (contains
* methods such as alterTable, createConstraint etc.)
* import Doctrine_Import driver, handles db schema reading
* sequence Doctrine_Sequence driver, handles sequential id generation and retrieval
* unitOfWork Doctrine_Connection_UnitOfWork handles many orm functionalities such as object
* formatter Doctrine_Formatter handles data formatting, quoting and escaping
* @see Doctrine_Connection::__get()
* @see Doctrine_Expression
* @see Doctrine_Transaction
* @see Doctrine_Connection_UnitOfWork
* @see Doctrine_Formatter
private $modules =
array('transaction' =>
false,
* @var array $properties an array of connection properties
protected $properties =
array('sql_comments' =>
array(array('start' =>
'--', 'end' =>
"\n", 'escape' =>
false),
array('start' =>
'/*', 'end' =>
'*/', 'escape' =>
false)),
'identifier_quoting' =>
array('start' =>
'"', 'end' =>
'"','escape' =>
'"'),
'string_quoting' =>
array('start' =>
"'",
'escape_pattern' =>
false),
'wildcards' =>
array('%', '_'),
'varchar_max_length' =>
255,
* @var array $availableDrivers an array containing all availible drivers
private static $availableDrivers =
array(
* @param Doctrine_Manager $manager the manager object
* @param PDO|Doctrine_Adapter_Interface$adapter database driver
public function __construct(Doctrine_Manager $manager, $adapter, $user =
null, $pass =
null)
$this->options['dsn'] =
$adapter['dsn'];
$this->options['username'] =
$adapter['user'];
$this->options['password'] =
$adapter['pass'];
* retrieves a database connection attribute
* @param integer $attribute
return $this->parent->getAttribute($attribute);
return $this->dbh->getAttribute($attribute);
* returns an array of available PDO drivers
return PDO::getAvailableDrivers();
* @param integer $attribute
$this->dbh->setAttribute($attribute, $value);
* returns the name of this driver
* @return string the name of this driver
* lazy loads given module and returns it
* @see Doctrine_Expression
* @see Doctrine_Transaction
* @see Doctrine_Connection::$modules all availible modules
* @param string $name the name of the module to get
* @throws Doctrine_Connection_Exception if trying to get an unknown module
* @return Doctrine_Connection_Module connection module
public function __get($name)
if ( ! isset
($this->modules[$name])) {
if ($this->modules[$name] ===
false) {
$this->modules[$name] =
new $class($this);
* returns the manager that created this connection
* @return Doctrine_Manager
* returns the database handler of which this connection uses
* @return PDO the database handler
if (in_array($e[0], PDO::getAvailableDrivers())) {
$this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$class =
'Doctrine_Adapter_' .
ucwords($e[0]);
// attach the pending attributes to adapter
// some drivers don't support setting this so we just skip it
if($attr ==
Doctrine::ATTR_DRIVER_NAME) {
$this->dbh->setAttribute($attr, $value);
* converts given driver name
* @param string $feature the name of the feature
* @return boolean whether or not this drivers supports given feature
&&
($this->supported[$feature] ===
'emulated'
* Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
* query, except that if there is already a row in the table with the same
* key field values, the REPLACE query just updates its values instead of
* The REPLACE type of query does not make part of the SQL standards. Since
* practically only MySQL and SQLIte implement it natively, this type of
* query isemulated through this method for other DBMS using standard types
* of queries inside a transaction to assure the atomicity of the operation.
* @param string name of the table on which the REPLACE query will
* @param array an associative array that describes the fields and the
* values that will be inserted or updated in the specified table. The
* indexes of the array are the names of all the fields of the table.
* The values of the array are values to be assigned to the specified field.
* @param array $keys an array containing all key fields (primary key fields
* or unique index fields) for this table
* the uniqueness of a row will be determined according to
* the provided key fields
* this method will fail if no key fields are specified
* @throws Doctrine_Connection_Exception if this driver doesn't support replace
* @throws Doctrine_Connection_Exception if some of the key values was null
* @throws Doctrine_Connection_Exception if there were no key fields
* @throws PDOException if something fails at PDO level
* @return integer number of rows affected
public function replace($table, array $fields, array $keys)
//if ( ! $this->supports('replace'))
// throw new Doctrine_Connection_Exception('replace query is not supported');
$condition =
$values =
array();
foreach ($fields as $name =>
$value) {
if (in_array($name, $keys)) {
$condition[] =
$name .
' = ?';
$conditionValues[] =
$value;
$affectedRows =
$this->exec($query);
$this->insert($table, $values);
* Inserts a table row with specified data.
* @param string $table The table to insert data into.
* @param array $values An associateve array containing column-value pairs.
public function insert($table, array $values =
array()) {
// column names are specified as array keys
// the query VALUES will contain either expresions (eg 'NOW()') or ?
foreach ($values as $k =>
$value) {
.
' (' .
implode(', ', $cols) .
') '
// prepare and execute the statement
* Set the charset on the current connection
* Quote a string so it can be safely used as a table or column name
* Delimiting style depends on which database driver is being used.
* NOTE: just because you CAN use delimited identifiers doesn't mean
* you SHOULD use them. In general, they end up causing way more
* problems than they solve.
* Portability is broken by using the following characters inside
* + backtick (<kbd>`</kbd>) -- due to MySQL
* + double quote (<kbd>"</kbd>) -- due to Oracle
* + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access
* Delimited identifiers are known to generally work correctly under
* InterBase doesn't seem to be able to use delimited identifiers
* via PHP 4. They work fine under PHP 5.
* @param string $str identifier name to be quoted
* @param bool $checkOption check the 'quote_identifier' option
* @return string quoted identifier string
// quick fix for the identifiers that contain a dot
* some drivers need the boolean values to be converted into integers
* This method takes care of that conversion
* quotes given input parameter
* @param mixed $input parameter to be quoted
public function quote($input, $type =
null)
return $this->formatter->quote($input, $type);
* Set the date/time format for the current connection
* @param string time format
* @param string $statement sql query to be executed
* @param array $params prepared statement params
public function fetchAll($statement, array $params =
array())
* @param string $statement sql query to be executed
* @param array $params prepared statement params
* @param int $colnum 0-indexed column number to retrieve
public function fetchOne($statement, array $params =
array(), $colnum =
0)
* @param string $statement sql query to be executed
* @param array $params prepared statement params
public function fetchRow($statement, array $params =
array())
* @param string $statement sql query to be executed
* @param array $params prepared statement params
public function fetchArray($statement, array $params =
array())
* @param string $statement sql query to be executed
* @param array $params prepared statement params
* @param int $colnum 0-indexed column number to retrieve
public function fetchColumn($statement, array $params =
array(), $colnum =
0)
* @param string $statement sql query to be executed
* @param array $params prepared statement params
public function fetchAssoc($statement, array $params =
array())
* @param string $statement sql query to be executed
* @param array $params prepared statement params
public function fetchBoth($statement, array $params =
array())
* queries the database using Doctrine Query Language
* returns a collection of Doctrine_Record objects
* $users = $conn->query('SELECT u.* FROM User u');
* $users = $conn->query('SELECT u.* FROM User u WHERE u.name LIKE ?', array('someone'));
* @param string $query DQL query
* @param array $params query parameters
* @return Doctrine_Collection Collection of Doctrine_Record objects
public function query($query, array $params =
array())
return $parser->query($query, $params);
* @param string $statement
public function prepare($statement)
if ( ! $event->skipOperation) {
} catch
(PDOException $e) { }
* queries the database using Doctrine Query Language and returns
* $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.id = ?', array(1));
* $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.name LIKE ? AND u.password = ?',
* array('someone', 'password')
* @param string $query DQL query
* @param array $params query parameters
* @return Doctrine_Record|false Doctrine_Record object on success,
* boolean false on failure
public function queryOne($query, array $params =
array())
$coll =
$parser->query($query, $params);
if ( ! $coll->contains(0)) {
* queries the database with limit and offset
* added to the query and returns a PDOStatement object
public function select($query, $limit =
0, $offset =
0)
if ($limit >
0 ||
$offset >
0) {
$query =
$this->modifyLimitQuery($query, $limit, $offset);
* @param string $query sql query
* @param array $params query parameters
* @return PDOStatement|Doctrine_Adapter_Statement
return $this->execute($query, $params);
* @param string $query sql query
* @param array $params query parameters
* @return PDOStatement|Doctrine_Adapter_Statement
public function execute($query, array $params =
array())
if ( ! $event->skipOperation) {
} catch
(PDOException $e) { }
* @param string $query sql query
* @param array $params query parameters
* @return PDOStatement|Doctrine_Adapter_Statement
public function exec($query, array $params =
array()) {
return $stmt->rowCount();
if ( ! $event->skipOperation) {
} catch
(PDOException $e) { }
* @throws Doctrine_Connection_Exception
$name =
'Doctrine_Connection_' .
$this->driverName .
'_Exception';
$exc =
new $name($e->getMessage(), (int)
$e->getCode());
$e->errorInfo =
array(null, null, null, null);
* whether or not this connection has table $name initialized
return isset
($this->tables[$name]);
* returns a table object for given component name
* @param string $name component name
* @return object Doctrine_Table
public function getTable($name, $allowExport =
true)
if (isset
($this->tables[$name])) {
$class =
$name .
'Table';
$table =
new $class($name, $this);
$this->tables[$name] =
$table;
* returns an array of all initialized tables
* returns an iterator that iterators through all
* initialized table objects
* foreach ($conn as $index => $table) {
* print $table; // get a string representation of each table object
* @return ArrayIterator SPL ArrayIterator object
return new ArrayIterator($this->tables);
* returns the count of initialized table objects
* adds a Doctrine_Table object into connection registry
* @param $table a Doctrine_Table object to be added into registry
public function addTable(Doctrine_Table $table)
$name =
$table->getComponentName();
if (isset
($this->tables[$name])) {
$this->tables[$name] =
$table;
* create creates a record
* @param string $name component name
* @return Doctrine_Record Doctrine_Record object
* saves all the records from all tables
* this operation is isolated using a transaction
* @throws PDOException if something went wrong at database level
$this->unitOfWork->saveAll();
* clears all repositories
foreach ($this->tables as $k =>
$table) {
$table->getRepository()->evictAll();
$this->exported =
array();
* get the current transaction nesting level
* Fetch the SQLSTATE associated with the last operation on the database handle
* Fetch extended error information associated with the last operation on the database handle
* Returns the ID of the last inserted row, or the last value from a sequence object,
* depending on the underlying driver.
* Note: This method may not return a meaningful or consistent result across different drivers,
* because the underlying database may not even support the notion of auto-increment fields or sequences.
* @param string $table name of the table into which a new row was inserted
* @param string $field name of the field into which a new row was inserted
* Start a transaction or set a savepoint.
* if trying to set a savepoint and there is no active transaction
* a new transaction is being started
* Listeners: onPreTransactionBegin, onTransactionBegin
* @param string $savepoint name of a savepoint to set
* @throws Doctrine_Transaction_Exception if the transaction fails at database level
* @return integer current transaction nesting level
* Commit the database changes done during a transaction that is in
* progress or release a savepoint. This function may only be called when
* auto-committing is disabled, otherwise it will fail.
* Listeners: onPreTransactionCommit, onTransactionCommit
* @param string $savepoint name of a savepoint to release
* @throws Doctrine_Transaction_Exception if the transaction fails at PDO level
* @throws Doctrine_Validator_Exception if the transaction fails due to record validations
* @return boolean false if commit couldn't be performed, true otherwise
public function commit($savepoint =
null)
$this->transaction->commit($savepoint);
* Cancel any database changes done during a transaction or since a specific
* savepoint that is in progress. This function may only be called when
* auto-committing is disabled, otherwise it will fail. Therefore, a new
* transaction is implicitly started after canceling the pending changes.
* this method can be listened with onPreTransactionRollback and onTransactionRollback
* @param string $savepoint name of a savepoint to rollback to
* @throws Doctrine_Transaction_Exception if the rollback operation fails at database level
* @return boolean false if rollback couldn't be performed, true otherwise
public function rollback($savepoint =
null)
$this->transaction->rollback($savepoint);
* returns a string representation of this object