Source for file Table.php
Documentation is available at Table.php
* $Id: Table.php 2279 2007-08-27 15:04:32Z Jonathan.Wage $
* 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>.
* Doctrine_Table represents a database table
* each Doctrine_Table holds the information of foreignKeys and associations
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version $Revision: 2279 $
* @category Object Relational Mapping
* @link www.phpdoctrine.com
* @var array $data temporary data which is then loaded into Doctrine_Record::$data
* @var array $primaryKeys an array containing all primary key column names
* @see Doctrine_Identifier constants
* @var integer $identifierType the type of identifier this table uses
* @var Doctrine_Connection $conn Doctrine_Connection object that created this table
* @var array $identityMap first level cache
* @var Doctrine_Table_Repository $repository record repository
* @var array $columns an array of column definitions,
* keys as column names and values as column definitions
* the definition array has atleast the following values:
* -- type the column type, eg. 'integer'
* -- length the column length, eg. 11
* -- notnull whether or not the column is marked as notnull
* -- notblank notblank validator + notnull constraint
* @var array $columnAliases an array of column aliases
* keys as column aliases and values as column names
* @var integer $columnCount cached column count, Doctrine_Record uses this column count in when
* @var boolean $hasDefaultValues whether or not this table has default values
* @var array $options an array containing all options
* -- name name of the component, for example component name of the GroupTable is 'Group'
* -- parents the parent classes of this component
* -- declaringClass name of the table definition declaring class (when using inheritance the class
* that defines the table structure can be any class in the inheritance hierarchy,
* hence we need reflection to check out which class actually calls setTableDefinition)
* -- tableName database table name, in most cases this is the same as component name but in some cases
* where one-table-multi-class inheritance is used this will be the name of the inherited table
* -- sequenceName Some databases need sequences instead of auto incrementation primary keys,
* you can set specific sequence for your table by calling setOption('sequenceName', $seqName)
* where $seqName is the name of the desired sequence
* -- enumMap enum value arrays
* -- inheritanceMap inheritanceMap is used for inheritance mapping, keys representing columns and values
* the column values that should correspond to child classes
* -- type table type (mysql example: INNODB)
* -- charset character set
* -- foreignKeys the foreign keys of this table
* -- checks the check constraints of this table, eg. 'price > dicounted_price'
* -- collation collation attribute
* -- indexes the index definitions of this table
* -- treeImpl the tree implementation of this table (if any)
* -- treeOptions the tree options
protected $options =
array('name' =>
null,
'inheritanceMap' =>
array(),
* @var Doctrine_Tree $tree tree object associated with this table
* @var Doctrine_Relation_Parser $_parser relation parser object
* @var array $_templates an array containing all templates attached to this table
* @throws Doctrine_Connection_Exception if there are no opened connections
* @throws Doctrine_Table_Exception if there is already an instance of this table
public function __construct($name, Doctrine_Connection $conn)
$record =
new $name($this);
if ($class ==
"Doctrine_Record") {
$this->options['parents'] =
$names;
$record->setTableDefinition();
// get the declaring class of setTableDefinition method
$method =
new ReflectionMethod($this->options['name'], 'setTableDefinition');
$class =
$method->getDeclaringClass();
$class =
new ReflectionClass($class);
$this->options['declaringClass'] =
$class;
// set the table definition for the given tree implementation
$this->getTree()->setTableDefinition();
if ( ! isset
($this->options['tableName'])) {
array('type' =>
'integer',
'primary' =>
true)), $this->columns);
foreach ($e as $option =>
$value) {
$this->options['sequenceName'] =
$value;
$this->options['sequenceName'] =
$sequence;
$this->options['sequenceName'] =
$this->conn->getSequenceName($this->options['tableName']);
* returns all templates attached to this table
* @return array an array containing all templates
* exports this table to database based on column and option definitions
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @return boolean whether or not the export operation was successful
* false if table already existed in the database
$this->conn->export->exportTable($this);
* returns exportable presentation of this object
foreach ($this->getColumns() as $name =>
$column) {
switch ($definition['type']) {
if (isset
($definition['default'])) {
$definition['default'] =
$this->enumIndex($name, $definition['default']);
if (isset
($definition['default'])) {
$definition['default'] =
$this->getConnection()->convertBooleans($definition['default']);
$columns[$name] =
$definition;
if(isset
($definition['primary']) &&
$definition['primary']) {
$options['foreignKeys'] =
array();
$emptyIntegrity =
array('onUpdate' =>
null,
$fk =
$relation->toArray();
$fk['foreignTable'] =
$relation->getTable()->getTableName();
if ($relation->getTable() ===
$this &&
in_array($relation->getLocal(), $primary)) {
if ($relation->hasConstraint()) {
$integrity =
array('onUpdate' =>
$fk['onUpdate'],
'onDelete' =>
$fk['onDelete']);
$def =
array('local' =>
$relation->getLocal(),
'foreign' =>
$relation->getForeign(),
'foreignTable' =>
$relation->getTable()->getTableName());
if (($key =
array_search($def, $options['foreignKeys'])) ===
false) {
$options['foreignKeys'][] =
$def;
$constraints[] =
$integrity;
if ($integrity !==
$emptyIntegrity) {
$constraints[$key] =
$integrity;
foreach ($constraints as $k =>
$def) {
$options['foreignKeys'][$k] =
array_merge($options['foreignKeys'][$k], $def);
$options['primary'] =
$primary;
return array('tableName' =>
$this->getOption('tableName'),
* exports the constraints of this table into database based on option definitions
* @throws Doctrine_Connection_Exception if something went wrong on db level
foreach ($this->options['index'] as $index =>
$definition) {
$this->conn->export->createIndex($this->options['tableName'], $index, $definition);
* return the relation parser associated with this table
* @return Doctrine_Relation_Parser relation parser object
public function __get($option)
if (isset
($this->options[$option])) {
return isset
($this->options[$option]);
* returns all options of this table and the associated values
* @return array all options and their values
* adds a foreignKey to this table
$this->options['foreignKeys'][] =
$definition;
* adds a check constraint to this table
public function addCheckConstraint($definition, $name)
$this->options['checks'][$name] =
$definition;
$this->options['checks'][] =
$definition;
* adds an index to this table
public function addIndex($index, array $definition)
$this->options['indexes'][$index] =
$definition;
* @return array|boolean array on success, FALSE on failure
public function getIndex($index)
if (isset
($this->options['indexes'][$index])) {
return $this->options['indexes'][$index];
public function bind($args, $type)
$options['type'] =
$type;
if ( ! isset
($args[1])) {
// the following is needed for backwards compatibility
if ( ! isset
($args[2])) {
$args[2] = (array)
$args[2];
$options['foreign'] =
$e[1];
$options['local'] =
$e[1];
if ($e[0] !==
$e2[0] &&
( ! isset
($e2[1]) ||
$e[0] !==
$e2[1])) {
$options['refClass'] =
$e[0];
$options['foreign'] =
$e[1];
* @param string $alias the relation to check if exists
* @return boolean true if the relation exists otherwise false
* @param string $alias relation alias
* returns an array containing all relation objects
* @return array an array of Doctrine_Relation objects
* creates a new Doctrine_Query object and adds the component name
* of this table as the query 'from' part
* @return Doctrine_Table_Repository
* sets an option and returns this object in order to
* allow flexible method chaining
* @see Doctrine_Table::$_options for available options
* @param string $name the name of the option to set
* @param mixed $value the value of the option
* @return Doctrine_Table this object
* returns the value of given option
* @param string $name the name of the option
* @return mixed the value of given option
if (isset
($this->options[$name])) {
* returns a column name for column alias
* if the actual name for the alias cannot be found
* this method returns the given alias
* @param string $alias column alias
* @return string column name
* @throws Doctrine_Table_Exception if trying use wrongly typed parameter
public function setColumn($name, $type, $length =
null, $options =
array())
foreach ($options as $k =>
$option) {
$options[$option] =
true;
// HH:NN:SS+00:00 ISO 8601
// YYYY-MM-DDTHH:MM:SS+00:00 ISO 8601
$this->columns[$name]['type'] =
$type;
$this->columns[$name]['length'] =
$length;
if (isset
($options['primary'])) {
if (isset
($options['default'])) {
* returns true if this table has default values, otherwise false
* returns the default value(if any) for given column
if ( ! isset
($this->columns[$column])) {
if (isset
($this->columns[$column]['default'])) {
return $this->columns[$column]['default'];
return isset
($this->columns[$name]);
* returns all primary keys
* @return Doctrine_Connection
* @param $array an array where keys are field names and values representing field values
* @return Doctrine_Record
public function create(array $array =
array()) {
$record =
new $this->options['name']($this, true);
* finds a record by its identifier
* @param $id database row id
* @return Doctrine_Record|false a record for given database identifier
public function find($id)
if (count($records) ===
0) {
return $records->getFirst();
* @param $where query where part to be modified
* @return string query where part with column aggregation inheritance added
if ( ! empty($this->options['inheritanceMap'])) {
foreach ($this->options['inheritanceMap'] as $field =>
$value) {
* returns a collection of records
* @return Doctrine_Collection
$users =
$graph->query('FROM ' .
$this->options['name']);
* finds records with given DQL where clause
* returns a collection of records
* @param string $dql DQL after WHERE clause
* @param array $params query parameters
* @return Doctrine_Collection
public function findBySql($dql, array $params =
array()) {
$users =
$q->query('FROM ' .
$this->options['name'] .
' WHERE ' .
$dql, $params);
public function findByDql($dql, array $params =
array()) {
* clears the first level cache (identityMap)
* adds a record to identity map
* @param Doctrine_Record $record record to be added
public function addRecord(Doctrine_Record $record)
$id =
implode(' ', $record->identifier());
* first checks if record exists in identityMap, if not
* @return Doctrine_Record
if ( ! empty($this->data)) {
if ( ! isset
($this->data[$k])) {
// primary key column not found return new record
$record =
new $recordName($this, true);
$record->hydrate($this->data);
$record =
new $recordName($this);
$record =
new $recordName($this, true);
* Get the classname to return. Most often this is just the options['name']
* Check the subclasses option and the inheritanceMap for each subclass to see
* if all the maps in a subclass is met. If this is the case return that
* subclass name. If no subclasses match or if there are no subclasses defined
* return the name of the class for this tables record.
* @todo this function could use reflection to check the first time it runs
* if the subclassing option is not set.
* @return string The name of the class to create
if (!isset
($this->options['subclasses'])) {
foreach ($this->options['subclasses'] as $subclass) {
$inheritanceMap =
$table->getOption('inheritanceMap');
foreach ($inheritanceMap as $key =>
$value) {
if ( ! isset
($this->data[$key]) ||
$this->data[$key] !=
$value) {
return $table->getComponentName();
* @param $id database row id
* @throws Doctrine_Find_Exception
final public function getProxy($id =
null)
$this->data =
$this->conn->execute($query, $params)->fetch(PDO::FETCH_ASSOC);
if ($this->data ===
false)
* @return Doctrine_Query a Doctrine_Query object
if (isset
($this->columns[$field]['values'])) {
return $this->columns[$field]['values'];
return isset
($this->columns[$field]['values'][$index]) ?
$this->columns[$field]['values'][$index] :
$index;
* @return integer the number of columns in this table
* returns all columns and their definitions
* returns an array containing all the column names
* @return mixed array on success, false on failure
if (isset
($this->columns[$column])) {
* @return mixed string on success, false on failure
if (isset
($this->columns[$column])) {
return $this->columns[$column]['type'];
* doctrine uses this function internally
* users are strongly discouraged to use this function
* @param array $data internal data
public function setData(array $data)
* returns internal data, used by Doctrine_Record instances
* when retrieving data from database
public function getData()
* this method performs special data preparation depending on
* the type of the given column
* 1. It unserializes array and object typed columns
* 2. Uncompresses gzip typed columns
* 3. Gets the appropriate enum values for enum typed columns
* 4. Initializes special null object pointer for null values (for fast column existence checking purposes)
* $table->prepareValue($field, $value); // Doctrine_Null
* @throws Doctrine_Table_Exception if unserialization of array/object typed column fails or
* @throws Doctrine_Table_Exception if uncompression of gzip typed column fails *
* @param string $field the name of the field
* @param string $value field value
* @return mixed prepared value
if ($value ===
self::$_null) {
} else if ($value ===
null) {
// don't do any casting here PHP INT_MAX is smaller than what the databases support
* getter for associated tree
* @return mixed if tree return instance of Doctrine_Tree, otherwise returns false
if (isset
($this->options['treeImpl'])) {
$options = isset
($this->options['treeOptions']) ?
$this->options['treeOptions'] :
array();
return $this->options['tableName'];
$this->options['tableName'] =
$tableName;
* determine if table acts as tree
* @return mixed if tree return true, otherwise returns false
public function addTemplate($template, Doctrine_Template $impl)
* returns a string representation of this object