From 6228873cf9d6471463d2413e7dfd7447f759baf2 Mon Sep 17 00:00:00 2001 From: "christophe.boulain" <> Date: Wed, 3 Dec 2008 14:22:03 +0000 Subject: Merge from trunk --- .../Exceptions/TActiveRecordException.php | 1 - .../Data/ActiveRecord/Exceptions/messages.txt | 3 +- .../Relations/TActiveRecordBelongsTo.php | 1 - .../Relations/TActiveRecordHasMany.php | 1 - .../Relations/TActiveRecordHasManyAssociation.php | 1 - .../ActiveRecord/Relations/TActiveRecordHasOne.php | 1 - .../Relations/TActiveRecordRelation.php | 1 - .../Relations/TActiveRecordRelationContext.php | 1 - .../Scaffold/InputBuilder/TIbmScaffoldInput.php | 1 - .../Scaffold/InputBuilder/TMssqlScaffoldInput.php | 1 - .../Scaffold/InputBuilder/TMysqlScaffoldInput.php | 1 - .../Scaffold/InputBuilder/TPgsqlScaffoldInput.php | 1 - .../Scaffold/InputBuilder/TScaffoldInputBase.php | 1 - .../Scaffold/InputBuilder/TScaffoldInputCommon.php | 1 - .../Scaffold/InputBuilder/TSqliteScaffoldInput.php | 1 - .../Data/ActiveRecord/Scaffold/TScaffoldBase.php | 1 - .../ActiveRecord/Scaffold/TScaffoldEditView.php | 1 - .../ActiveRecord/Scaffold/TScaffoldListView.php | 1 - .../Data/ActiveRecord/Scaffold/TScaffoldSearch.php | 1 - .../Data/ActiveRecord/Scaffold/TScaffoldView.php | 1 - framework/Data/ActiveRecord/TActiveRecord.php | 29 +- .../Data/ActiveRecord/TActiveRecordConfig.php | 1 - .../Data/ActiveRecord/TActiveRecordCriteria.php | 1 - .../Data/ActiveRecord/TActiveRecordGateway.php | 839 +++++++++++---------- .../Data/ActiveRecord/TActiveRecordManager.php | 1 - 25 files changed, 452 insertions(+), 441 deletions(-) (limited to 'framework/Data/ActiveRecord') diff --git a/framework/Data/ActiveRecord/Exceptions/TActiveRecordException.php b/framework/Data/ActiveRecord/Exceptions/TActiveRecordException.php index be88f015..eaab5735 100644 --- a/framework/Data/ActiveRecord/Exceptions/TActiveRecordException.php +++ b/framework/Data/ActiveRecord/Exceptions/TActiveRecordException.php @@ -39,4 +39,3 @@ class TActiveRecordConfigurationException extends TActiveRecordException } -?> diff --git a/framework/Data/ActiveRecord/Exceptions/messages.txt b/framework/Data/ActiveRecord/Exceptions/messages.txt index fabfc1a4..0702c840 100644 --- a/framework/Data/ActiveRecord/Exceptions/messages.txt +++ b/framework/Data/ActiveRecord/Exceptions/messages.txt @@ -10,6 +10,7 @@ ar_primary_key_is_scalar = Primary key '{1}' in table '{0}' is NOT a composi ar_invalid_db_connection = Missing or invalid default database connection for ActiveRecord class '{0}', default connection is set by the DbConnection property of TActiveRecordManager. ar_mismatch_args_exception = ActiveRecord finder method '{0}' expects {1} parameters but found only {2} parameters instead. ar_invalid_tablename_property = Constant {0}::{1} must be a valid database table name. +ar_invalid_tablename_method = Method {0}::{1} must return a valid database table name. ar_value_must_not_be_null = Property '{0}::${2}' must not be null as defined by column '{2}' in table '{1}'. ar_missing_pk_values = Missing primary key values in forming IN(key1, key2, ...) for table '{0}'. ar_pk_value_count_mismatch = Composite key value count mismatch in forming IN( (key1, key2, ..), (key3, key4, ..)) for table '{0}'. @@ -21,4 +22,4 @@ ar_invalid_criteria = Invalid criteria object, must be a string or instanc ar_relations_undefined = Unable to determine Active Record relationships because static array property {0}::${1} is not defined. ar_undefined_relation_prop = Unable to find {1}::${2}['{0}'], Active Record relationship definition for property "{0}" not found in entries of {1}::${2}. ar_invalid_relationship = Invalid active record relationship. -ar_relations_missing_fk = Unable to find foreign key relationships in table '{0}' that corresponds to table '{1}'. \ No newline at end of file +ar_relations_missing_fk = Unable to find foreign key relationships in table '{0}' that corresponds to table '{1}'. diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordBelongsTo.php b/framework/Data/ActiveRecord/Relations/TActiveRecordBelongsTo.php index 9f8777e2..40936011 100644 --- a/framework/Data/ActiveRecord/Relations/TActiveRecordBelongsTo.php +++ b/framework/Data/ActiveRecord/Relations/TActiveRecordBelongsTo.php @@ -136,4 +136,3 @@ class TActiveRecordBelongsTo extends TActiveRecordRelation } } -?> diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordHasMany.php b/framework/Data/ActiveRecord/Relations/TActiveRecordHasMany.php index c66afa14..6f191b9f 100644 --- a/framework/Data/ActiveRecord/Relations/TActiveRecordHasMany.php +++ b/framework/Data/ActiveRecord/Relations/TActiveRecordHasMany.php @@ -119,4 +119,3 @@ class TActiveRecordHasMany extends TActiveRecordRelation } } -?> diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php b/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php index 9b01d323..4c71f91c 100644 --- a/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php +++ b/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php @@ -374,4 +374,3 @@ class TActiveRecordHasManyAssociation extends TActiveRecordRelation return $data; } } -?> diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordHasOne.php b/framework/Data/ActiveRecord/Relations/TActiveRecordHasOne.php index 6e8d30de..b1aa7b91 100644 --- a/framework/Data/ActiveRecord/Relations/TActiveRecordHasOne.php +++ b/framework/Data/ActiveRecord/Relations/TActiveRecordHasOne.php @@ -143,4 +143,3 @@ class TActiveRecordHasOne extends TActiveRecordRelation } } -?> diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php b/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php index 4044a5ce..a352cb07 100644 --- a/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php +++ b/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php @@ -247,4 +247,3 @@ abstract class TActiveRecordRelation } } -?> diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php b/framework/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php index 329007af..696bb5b1 100644 --- a/framework/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php +++ b/framework/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php @@ -228,4 +228,3 @@ class TActiveRecordRelationContext } } -?> diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TIbmScaffoldInput.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TIbmScaffoldInput.php index 05de2019..c8177d5e 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TIbmScaffoldInput.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TIbmScaffoldInput.php @@ -49,4 +49,3 @@ class TIbmScaffoldInput extends TScaffoldInputCommon } } -?> diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMssqlScaffoldInput.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMssqlScaffoldInput.php index bca1bcb2..be495e98 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMssqlScaffoldInput.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMssqlScaffoldInput.php @@ -51,4 +51,3 @@ class TMssqlScaffoldInput extends TScaffoldInputCommon } } -?> diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMysqlScaffoldInput.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMysqlScaffoldInput.php index a8ecdd13..c06e4113 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMysqlScaffoldInput.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMysqlScaffoldInput.php @@ -81,4 +81,3 @@ class TMysqlScaffoldInput extends TScaffoldInputCommon } } -?> diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TPgsqlScaffoldInput.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TPgsqlScaffoldInput.php index 69b67e7f..cd244b27 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TPgsqlScaffoldInput.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TPgsqlScaffoldInput.php @@ -52,4 +52,3 @@ class TPgsqlScaffoldInput extends TScaffoldInputCommon } } -?> diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputBase.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputBase.php index ad563f2f..d8db9c59 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputBase.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputBase.php @@ -101,4 +101,3 @@ class TScaffoldInputBase } } -?> diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputCommon.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputCommon.php index 12f9bc25..d02bc9a0 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputCommon.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputCommon.php @@ -307,4 +307,3 @@ class TScaffoldInputCommon extends TScaffoldInputBase } } -?> diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TSqliteScaffoldInput.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TSqliteScaffoldInput.php index c187e825..5f431067 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TSqliteScaffoldInput.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TSqliteScaffoldInput.php @@ -97,4 +97,3 @@ class TSqliteScaffoldInput extends TScaffoldInputCommon } } -?> diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php index 1e9b87e7..9c548308 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php @@ -204,4 +204,3 @@ abstract class TScaffoldBase extends TTemplateControl } } -?> diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php index 1760b27d..b38b739f 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php @@ -307,4 +307,3 @@ interface IScaffoldEditRenderer extends IDataRenderer public function updateRecord($record); } -?> diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php index 79ab40ab..6c28651a 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php @@ -304,4 +304,3 @@ class TScaffoldListView extends TScaffoldBase } } -?> diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldSearch.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldSearch.php index a7f58735..b1cd6cbc 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldSearch.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldSearch.php @@ -148,4 +148,3 @@ class TScaffoldSearch extends TScaffoldBase } } -?> diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldView.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldView.php index 1ddba335..04420e9a 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldView.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldView.php @@ -141,4 +141,3 @@ class TScaffoldView extends TScaffoldBase } } -?> diff --git a/framework/Data/ActiveRecord/TActiveRecord.php b/framework/Data/ActiveRecord/TActiveRecord.php index 370dd69a..fa134a9f 100644 --- a/framework/Data/ActiveRecord/TActiveRecord.php +++ b/framework/Data/ActiveRecord/TActiveRecord.php @@ -79,7 +79,7 @@ Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelationContext'); * 'email_address'=>'email', * ); * public $username; - * pulbic $email; + * public $email; * } * * In the above, the 'users' table consists of 'user_id' and 'email_address' columns, @@ -129,6 +129,18 @@ Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelationContext'); * } * * + * Since v3.1.3 you can also define a method that returns the table name. + * + * class UserRecord extends TActiveRecord + * { + * public function table() + * { + * return 'users'; + * } + * + * } + * + * * @author Wei Zhuo * @version $Id$ * @package System.Data.ActiveRecord @@ -317,6 +329,14 @@ abstract class TActiveRecord extends TComponent $this->_connection=$connection; } + /** + * @return TDbTableInfo the meta information of the table associated with this AR class. + */ + public function getRecordTableInfo() + { + return $this->getRecordGateway()->getRecordTableInfo($this); + } + /** * Compare two records using their primary key values (all column values if * table does not defined primary keys). The default uses simple == for @@ -329,7 +349,7 @@ abstract class TActiveRecord extends TComponent { if($record===null || get_class($this)!==get_class($record)) return false; - $tableInfo = $this->getRecordGateway()->getRecordTableInfo($this); + $tableInfo = $this->getRecordTableInfo(); $pks = $tableInfo->getPrimaryKeys(); $properties = count($pks) > 0 ? $pks : $tableInfo->getColumns()->getKeys(); $equals=true; @@ -378,7 +398,7 @@ abstract class TActiveRecord extends TComponent /** * @return TActiveRecordGateway record table gateway. */ - public static function getRecordGateway() + public function getRecordGateway() { return TActiveRecordManager::getInstance()->getRecordGateway(); } @@ -552,6 +572,7 @@ abstract class TActiveRecord extends TComponent { $args = func_num_args() > 1 ? array_slice(func_get_args(),1) : null; $criteria = $this->getRecordCriteria($criteria,$parameters, $args); + $criteria->setLimit(1); $data = $this->getRecordGateway()->findRecordsByCriteria($this,$criteria); return $this->populateObject($data); } @@ -629,6 +650,7 @@ abstract class TActiveRecord extends TComponent { $args = func_num_args() > 1 ? array_slice(func_get_args(),1) : null; $criteria = $this->getRecordCriteria($sql,$parameters, $args); + $criteria->setLimit(1); $data = $this->getRecordGateway()->findRecordBySql($this,$criteria); return $this->populateObject($data); } @@ -1000,4 +1022,3 @@ class TActiveRecordChangeEventParameter extends TEventParameter } } -?> diff --git a/framework/Data/ActiveRecord/TActiveRecordConfig.php b/framework/Data/ActiveRecord/TActiveRecordConfig.php index 4e21635e..63f05aef 100644 --- a/framework/Data/ActiveRecord/TActiveRecordConfig.php +++ b/framework/Data/ActiveRecord/TActiveRecordConfig.php @@ -105,4 +105,3 @@ class TActiveRecordConfig extends TDataSourceConfig } } -?> diff --git a/framework/Data/ActiveRecord/TActiveRecordCriteria.php b/framework/Data/ActiveRecord/TActiveRecordCriteria.php index eec6df04..41e8ad02 100644 --- a/framework/Data/ActiveRecord/TActiveRecordCriteria.php +++ b/framework/Data/ActiveRecord/TActiveRecordCriteria.php @@ -37,4 +37,3 @@ class TActiveRecordCriteria extends TSqlCriteria } -?> diff --git a/framework/Data/ActiveRecord/TActiveRecordGateway.php b/framework/Data/ActiveRecord/TActiveRecordGateway.php index 23104c00..6cce9eb9 100644 --- a/framework/Data/ActiveRecord/TActiveRecordGateway.php +++ b/framework/Data/ActiveRecord/TActiveRecordGateway.php @@ -1,414 +1,425 @@ - - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2008 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Data.ActiveRecord - */ - -/** - * TActiveRecordGateway excutes the SQL command queries and returns the data - * record as arrays (for most finder methods). - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.ActiveRecord - * @since 3.1 - */ -class TActiveRecordGateway extends TComponent -{ - private $_manager; - private $_tables=array(); //table cache - private $_meta=array(); //meta data cache. - private $_commandBuilders=array(); - private $_currentRecord; - - /** - * Constant name for specifying optional table name in TActiveRecord. - */ - const TABLE_CONST='TABLE'; - - /** - * Record gateway constructor. - * @param TActiveRecordManager $manager - */ - public function __construct(TActiveRecordManager $manager) - { - $this->_manager=$manager; - } - - /** - * @return TActiveRecordManager record manager. - */ - protected function getManager() - { - return $this->_manager; - } - - /** - * Gets the table name from the 'TABLE' constant of the active record - * class if defined, otherwise use the class name as table name. - * @param TActiveRecord active record instance - * @return string table name for the given record class. - */ - protected function getRecordTableName(TActiveRecord $record) - { - $class = new ReflectionClass($record); - if($class->hasConstant(self::TABLE_CONST)) - { - $value = $class->getConstant(self::TABLE_CONST); - if(empty($value)) - throw new TActiveRecordException('ar_invalid_tablename_property', - get_class($record),self::TABLE_CONST); - return $value; - } - else - return strtolower(get_class($record)); - } - - /** - * Returns table information, trys the application cache first. - * @param TActiveRecord $record - * @return TDbTableInfo table information. - */ - public function getRecordTableInfo(TActiveRecord $record) - { - $tableName = $this->getRecordTableName($record); - return $this->getTableInfo($record->getDbConnection(), $tableName); - } - - /** - * Returns table information for table in the database connection. - * @param TDbConnection database connection - * @param string table name - * @return TDbTableInfo table details. - */ - public function getTableInfo(TDbConnection $connection, $tableName) - { - $connStr = $connection->getConnectionString(); - $key = $connStr.$tableName; - if(!isset($this->_tables[$key])) - { - //call this first to ensure that unserializing the cache - //will find the correct driver dependent classes. - if(!isset($this->_meta[$connStr])) - { - Prado::using('System.Data.Common.TDbMetaData'); - $this->_meta[$connStr] = TDbMetaData::getInstance($connection); - } - - $tableInfo = null; - if(($cache=$this->getManager()->getCache())!==null) - $tableInfo = $cache->get($key); - if(empty($tableInfo)) - { - $tableInfo = $this->_meta[$connStr]->getTableInfo($tableName); - if($cache!==null) - $cache->set($key, $tableInfo); - } - $this->_tables[$key] = $tableInfo; - } - return $this->_tables[$key]; - } - - /** - * @param TActiveRecord $record - * @return TDataGatewayCommand - */ - public function getCommand(TActiveRecord $record) - { - $conn = $record->getDbConnection(); - $connStr = $conn->getConnectionString(); - $tableInfo = $this->getRecordTableInfo($record); - if(!isset($this->_commandBuilders[$connStr])) - { - $builder = $tableInfo->createCommandBuilder($record->getDbConnection()); - Prado::using('System.Data.DataGateway.TDataGatewayCommand'); - $command = new TDataGatewayCommand($builder); - $command->OnCreateCommand[] = array($this, 'onCreateCommand'); - $command->OnExecuteCommand[] = array($this, 'onExecuteCommand'); - $this->_commandBuilders[$connStr] = $command; - - } - $this->_commandBuilders[$connStr]->getBuilder()->setTableInfo($tableInfo); - $this->_currentRecord=$record; - return $this->_commandBuilders[$connStr]; - } - - /** - * Raised when a command is prepared and parameter binding is completed. - * The parameter object is TDataGatewayEventParameter of which the - * {@link TDataGatewayEventParameter::getCommand Command} property can be - * inspected to obtain the sql query to be executed. - * This method also raises the OnCreateCommand event on the ActiveRecord - * object calling this gateway. - * @param TDataGatewayCommand originator $sender - * @param TDataGatewayEventParameter - */ - public function onCreateCommand($sender, $param) - { - $this->raiseEvent('OnCreateCommand', $this, $param); - if($this->_currentRecord!==null) - $this->_currentRecord->onCreateCommand($param); - } - - /** - * Raised when a command is executed and the result from the database was returned. - * The parameter object is TDataGatewayResultEventParameter of which the - * {@link TDataGatewayEventParameter::getResult Result} property contains - * the data return from the database. The data returned can be changed - * by setting the {@link TDataGatewayEventParameter::setResult Result} property. - * This method also raises the OnCreateCommand event on the ActiveRecord - * object calling this gateway. - * @param TDataGatewayCommand originator $sender - * @param TDataGatewayResultEventParameter - */ - public function onExecuteCommand($sender, $param) - { - $this->raiseEvent('OnExecuteCommand', $this, $param); - if($this->_currentRecord!==null) - $this->_currentRecord->onExecuteCommand($param); - } - - /** - * Returns record data matching the given primary key(s). If the table uses - * composite key, specify the name value pairs as an array. - * @param TActiveRecord active record instance. - * @param array primary name value pairs - * @return array record data - */ - public function findRecordByPK(TActiveRecord $record,$keys) - { - $command = $this->getCommand($record); - return $command->findByPk($keys); - } - - /** - * Returns records matching the list of given primary keys. - * @param TActiveRecord active record instance. - * @param array list of primary name value pairs - * @return array matching data. - */ - public function findRecordsByPks(TActiveRecord $record, $keys) - { - return $this->getCommand($record)->findAllByPk($keys); - } - - - /** - * Returns record data matching the given critera. If $iterator is true, it will - * return multiple rows as TDbDataReader otherwise it returns the first row data. - * @param TActiveRecord active record finder instance. - * @param TActiveRecordCriteria search criteria. - * @param boolean true to return multiple rows as iterator, false returns first row. - * @return mixed matching data. - */ - public function findRecordsByCriteria(TActiveRecord $record, $criteria, $iterator=false) - { - $command = $this->getCommand($record); - return $iterator ? $command->findAll($criteria) : $command->find($criteria); - } - - /** - * Return record data from sql query. - * @param TActiveRecord active record finder instance. - * @param TActiveRecordCriteria sql query - * @return array result. - */ - public function findRecordBySql(TActiveRecord $record, $criteria) - { - return $this->getCommand($record)->findBySql($criteria); - } - - /** - * Return record data from sql query. - * @param TActiveRecord active record finder instance. - * @param TActiveRecordCriteria sql query - * @return TDbDataReader result iterator. - */ - public function findRecordsBySql(TActiveRecord $record, $criteria) - { - return $this->getCommand($record)->findAllBySql($criteria); - } - - public function findRecordsByIndex(TActiveRecord $record, $criteria, $fields, $values) - { - return $this->getCommand($record)->findAllByIndex($criteria,$fields,$values); - } - - /** - * Returns the number of records that match the given criteria. - * @param TActiveRecord active record finder instance. - * @param TActiveRecordCriteria search criteria - * @return int number of records. - */ - public function countRecords(TActiveRecord $record, $criteria) - { - return $this->getCommand($record)->count($criteria); - } - - /** - * Insert a new record. - * @param TActiveRecord new record. - * @return int number of rows affected. - */ - public function insert(TActiveRecord $record) - { - //$this->updateAssociatedRecords($record,true); - $result = $this->getCommand($record)->insert($this->getInsertValues($record)); - if($result) - $this->updatePostInsert($record); - //$this->updateAssociatedRecords($record); - return $result; - } - - /** - * Sets the last insert ID to the corresponding property of the record if available. - * @param TActiveRecord record for insertion - */ - protected function updatePostInsert($record) - { - $command = $this->getCommand($record); - $tableInfo = $command->getTableInfo(); - foreach($tableInfo->getColumns() as $name => $column) - { - if($column->hasSequence()) - $record->setColumnValue($name,$command->getLastInsertID($column->getSequenceName())); - } - } - - /** - * @param TActiveRecord record - * @return array insert values. - */ - protected function getInsertValues(TActiveRecord $record) - { - $values=array(); - $tableInfo = $this->getCommand($record)->getTableInfo(); - foreach($tableInfo->getColumns() as $name=>$column) - { - if($column->getIsExcluded()) - continue; - $value = $record->getColumnValue($name); - if(!$column->getAllowNull() && $value===null && !$column->hasSequence()) - { - throw new TActiveRecordException( - 'ar_value_must_not_be_null', get_class($record), - $tableInfo->getTableFullName(), $name); - } - if($value!==null) - $values[$name] = $value; - } - return $values; - } - - /** - * Update the record. - * @param TActiveRecord dirty record. - * @return int number of rows affected. - */ - public function update(TActiveRecord $record) - { - //$this->updateAssociatedRecords($record,true); - list($data, $keys) = $this->getUpdateValues($record); - $result = $this->getCommand($record)->updateByPk($data, $keys); - //$this->updateAssociatedRecords($record); - return $result; - } - - protected function getUpdateValues(TActiveRecord $record) - { - $values=array(); - $tableInfo = $this->getCommand($record)->getTableInfo(); - $primary=array(); - foreach($tableInfo->getColumns() as $name=>$column) - { - if($column->getIsExcluded()) - continue; - $value = $record->getColumnValue($name); - if(!$column->getAllowNull() && $value===null) - { - throw new TActiveRecordException( - 'ar_value_must_not_be_null', get_class($record), - $tableInfo->getTableFullName(), $name); - } - if($column->getIsPrimaryKey()) - $primary[] = $value; - else - $values[$name] = $value; - } - return array($values,$primary); - } - - protected function updateAssociatedRecords(TActiveRecord $record,$updateBelongsTo=false) - { - $context = new TActiveRecordRelationContext($record); - return $context->updateAssociatedRecords($updateBelongsTo); - } - - /** - * Delete the record. - * @param TActiveRecord record to be deleted. - * @return int number of rows affected. - */ - public function delete(TActiveRecord $record) - { - return $this->getCommand($record)->deleteByPk($this->getPrimaryKeyValues($record)); - } - - protected function getPrimaryKeyValues(TActiveRecord $record) - { - $tableInfo = $this->getCommand($record)->getTableInfo(); - $primary=array(); - foreach($tableInfo->getColumns() as $name=>$column) - { - if($column->getIsPrimaryKey()) - $primary[$name] = $record->getColumnValue($name); - } - return $primary; - } - - /** - * Delete multiple records using primary keys. - * @param TActiveRecord finder instance. - * @return int number of rows deleted. - */ - public function deleteRecordsByPk(TActiveRecord $record, $keys) - { - return $this->getCommand($record)->deleteByPk($keys); - } - - /** - * Delete multiple records by criteria. - * @param TActiveRecord active record finder instance. - * @param TActiveRecordCriteria search criteria - * @return int number of records. - */ - public function deleteRecordsByCriteria(TActiveRecord $record, $criteria) - { - return $this->getCommand($record)->delete($criteria); - } - - /** - * Raise the corresponding command event, insert, update, delete or select. - * @param string command type - * @param TDbCommand sql command to be executed. - * @param TActiveRecord active record - * @param TActiveRecordCriteria data for the command. - */ - protected function raiseCommandEvent($event,$command,$record,$criteria) - { - if(!($criteria instanceof TSqlCriteria)) - $criteria = new TActiveRecordCriteria(null,$criteria); - $param = new TActiveRecordEventParameter($command,$record,$criteria); - $manager = $record->getRecordManager(); - $manager->{$event}($param); - $record->{$event}($param); - } -} - -?> + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2008 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.ActiveRecord + */ + +/** + * TActiveRecordGateway excutes the SQL command queries and returns the data + * record as arrays (for most finder methods). + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.ActiveRecord + * @since 3.1 + */ +class TActiveRecordGateway extends TComponent +{ + private $_manager; + private $_tables=array(); //table cache + private $_meta=array(); //meta data cache. + private $_commandBuilders=array(); + private $_currentRecord; + + /** + * Constant name for specifying optional table name in TActiveRecord. + */ + const TABLE_CONST='TABLE'; + /** + * Method name for returning optional table name in in TActiveRecord + */ + const TABLE_METHOD='table'; + + /** + * Record gateway constructor. + * @param TActiveRecordManager $manager + */ + public function __construct(TActiveRecordManager $manager) + { + $this->_manager=$manager; + } + + /** + * @return TActiveRecordManager record manager. + */ + protected function getManager() + { + return $this->_manager; + } + + /** + * Gets the table name from the 'TABLE' constant of the active record + * class if defined, otherwise use the class name as table name. + * @param TActiveRecord active record instance + * @return string table name for the given record class. + */ + protected function getRecordTableName(TActiveRecord $record) + { + $class = new ReflectionClass($record); + if($class->hasConstant(self::TABLE_CONST)) + { + $value = $class->getConstant(self::TABLE_CONST); + if(empty($value)) + throw new TActiveRecordException('ar_invalid_tablename_property', + get_class($record),self::TABLE_CONST); + return $value; + } + elseif ($class->hasMethod(self::TABLE_METHOD)) + { + $value = $record->{self::TABLE_METHOD}(); + if(empty($value)) + throw new TActiveRecordException('ar_invalid_tablename_method', + get_class($record),self::TABLE_METHOD); + return $value; + } + else + return strtolower(get_class($record)); + } + + /** + * Returns table information, trys the application cache first. + * @param TActiveRecord $record + * @return TDbTableInfo table information. + */ + public function getRecordTableInfo(TActiveRecord $record) + { + $tableName = $this->getRecordTableName($record); + return $this->getTableInfo($record->getDbConnection(), $tableName); + } + + /** + * Returns table information for table in the database connection. + * @param TDbConnection database connection + * @param string table name + * @return TDbTableInfo table details. + */ + public function getTableInfo(TDbConnection $connection, $tableName) + { + $connStr = $connection->getConnectionString(); + $key = $connStr.$tableName; + if(!isset($this->_tables[$key])) + { + //call this first to ensure that unserializing the cache + //will find the correct driver dependent classes. + if(!isset($this->_meta[$connStr])) + { + Prado::using('System.Data.Common.TDbMetaData'); + $this->_meta[$connStr] = TDbMetaData::getInstance($connection); + } + + $tableInfo = null; + if(($cache=$this->getManager()->getCache())!==null) + $tableInfo = $cache->get($key); + if(empty($tableInfo)) + { + $tableInfo = $this->_meta[$connStr]->getTableInfo($tableName); + if($cache!==null) + $cache->set($key, $tableInfo); + } + $this->_tables[$key] = $tableInfo; + } + return $this->_tables[$key]; + } + + /** + * @param TActiveRecord $record + * @return TDataGatewayCommand + */ + public function getCommand(TActiveRecord $record) + { + $conn = $record->getDbConnection(); + $connStr = $conn->getConnectionString(); + $tableInfo = $this->getRecordTableInfo($record); + if(!isset($this->_commandBuilders[$connStr])) + { + $builder = $tableInfo->createCommandBuilder($record->getDbConnection()); + Prado::using('System.Data.DataGateway.TDataGatewayCommand'); + $command = new TDataGatewayCommand($builder); + $command->OnCreateCommand[] = array($this, 'onCreateCommand'); + $command->OnExecuteCommand[] = array($this, 'onExecuteCommand'); + $this->_commandBuilders[$connStr] = $command; + + } + $this->_commandBuilders[$connStr]->getBuilder()->setTableInfo($tableInfo); + $this->_currentRecord=$record; + return $this->_commandBuilders[$connStr]; + } + + /** + * Raised when a command is prepared and parameter binding is completed. + * The parameter object is TDataGatewayEventParameter of which the + * {@link TDataGatewayEventParameter::getCommand Command} property can be + * inspected to obtain the sql query to be executed. + * This method also raises the OnCreateCommand event on the ActiveRecord + * object calling this gateway. + * @param TDataGatewayCommand originator $sender + * @param TDataGatewayEventParameter + */ + public function onCreateCommand($sender, $param) + { + $this->raiseEvent('OnCreateCommand', $this, $param); + if($this->_currentRecord!==null) + $this->_currentRecord->onCreateCommand($param); + } + + /** + * Raised when a command is executed and the result from the database was returned. + * The parameter object is TDataGatewayResultEventParameter of which the + * {@link TDataGatewayEventParameter::getResult Result} property contains + * the data return from the database. The data returned can be changed + * by setting the {@link TDataGatewayEventParameter::setResult Result} property. + * This method also raises the OnCreateCommand event on the ActiveRecord + * object calling this gateway. + * @param TDataGatewayCommand originator $sender + * @param TDataGatewayResultEventParameter + */ + public function onExecuteCommand($sender, $param) + { + $this->raiseEvent('OnExecuteCommand', $this, $param); + if($this->_currentRecord!==null) + $this->_currentRecord->onExecuteCommand($param); + } + + /** + * Returns record data matching the given primary key(s). If the table uses + * composite key, specify the name value pairs as an array. + * @param TActiveRecord active record instance. + * @param array primary name value pairs + * @return array record data + */ + public function findRecordByPK(TActiveRecord $record,$keys) + { + $command = $this->getCommand($record); + return $command->findByPk($keys); + } + + /** + * Returns records matching the list of given primary keys. + * @param TActiveRecord active record instance. + * @param array list of primary name value pairs + * @return array matching data. + */ + public function findRecordsByPks(TActiveRecord $record, $keys) + { + return $this->getCommand($record)->findAllByPk($keys); + } + + + /** + * Returns record data matching the given critera. If $iterator is true, it will + * return multiple rows as TDbDataReader otherwise it returns the first row data. + * @param TActiveRecord active record finder instance. + * @param TActiveRecordCriteria search criteria. + * @param boolean true to return multiple rows as iterator, false returns first row. + * @return mixed matching data. + */ + public function findRecordsByCriteria(TActiveRecord $record, $criteria, $iterator=false) + { + $command = $this->getCommand($record); + return $iterator ? $command->findAll($criteria) : $command->find($criteria); + } + + /** + * Return record data from sql query. + * @param TActiveRecord active record finder instance. + * @param TActiveRecordCriteria sql query + * @return array result. + */ + public function findRecordBySql(TActiveRecord $record, $criteria) + { + return $this->getCommand($record)->findBySql($criteria); + } + + /** + * Return record data from sql query. + * @param TActiveRecord active record finder instance. + * @param TActiveRecordCriteria sql query + * @return TDbDataReader result iterator. + */ + public function findRecordsBySql(TActiveRecord $record, $criteria) + { + return $this->getCommand($record)->findAllBySql($criteria); + } + + public function findRecordsByIndex(TActiveRecord $record, $criteria, $fields, $values) + { + return $this->getCommand($record)->findAllByIndex($criteria,$fields,$values); + } + + /** + * Returns the number of records that match the given criteria. + * @param TActiveRecord active record finder instance. + * @param TActiveRecordCriteria search criteria + * @return int number of records. + */ + public function countRecords(TActiveRecord $record, $criteria) + { + return $this->getCommand($record)->count($criteria); + } + + /** + * Insert a new record. + * @param TActiveRecord new record. + * @return int number of rows affected. + */ + public function insert(TActiveRecord $record) + { + //$this->updateAssociatedRecords($record,true); + $result = $this->getCommand($record)->insert($this->getInsertValues($record)); + if($result) + $this->updatePostInsert($record); + //$this->updateAssociatedRecords($record); + return $result; + } + + /** + * Sets the last insert ID to the corresponding property of the record if available. + * @param TActiveRecord record for insertion + */ + protected function updatePostInsert($record) + { + $command = $this->getCommand($record); + $tableInfo = $command->getTableInfo(); + foreach($tableInfo->getColumns() as $name => $column) + { + if($column->hasSequence()) + $record->setColumnValue($name,$command->getLastInsertID($column->getSequenceName())); + } + } + + /** + * @param TActiveRecord record + * @return array insert values. + */ + protected function getInsertValues(TActiveRecord $record) + { + $values=array(); + $tableInfo = $this->getCommand($record)->getTableInfo(); + foreach($tableInfo->getColumns() as $name=>$column) + { + if($column->getIsExcluded()) + continue; + $value = $record->getColumnValue($name); + if(!$column->getAllowNull() && $value===null && !$column->hasSequence() && !$column->getDefaultValue()) + { + throw new TActiveRecordException( + 'ar_value_must_not_be_null', get_class($record), + $tableInfo->getTableFullName(), $name); + } + if($value!==null) + $values[$name] = $value; + } + return $values; + } + + /** + * Update the record. + * @param TActiveRecord dirty record. + * @return int number of rows affected. + */ + public function update(TActiveRecord $record) + { + //$this->updateAssociatedRecords($record,true); + list($data, $keys) = $this->getUpdateValues($record); + $result = $this->getCommand($record)->updateByPk($data, $keys); + //$this->updateAssociatedRecords($record); + return $result; + } + + protected function getUpdateValues(TActiveRecord $record) + { + $values=array(); + $tableInfo = $this->getCommand($record)->getTableInfo(); + $primary=array(); + foreach($tableInfo->getColumns() as $name=>$column) + { + if($column->getIsExcluded()) + continue; + $value = $record->getColumnValue($name); + if(!$column->getAllowNull() && $value===null) + { + throw new TActiveRecordException( + 'ar_value_must_not_be_null', get_class($record), + $tableInfo->getTableFullName(), $name); + } + if($column->getIsPrimaryKey()) + $primary[] = $value; + else + $values[$name] = $value; + } + return array($values,$primary); + } + + protected function updateAssociatedRecords(TActiveRecord $record,$updateBelongsTo=false) + { + $context = new TActiveRecordRelationContext($record); + return $context->updateAssociatedRecords($updateBelongsTo); + } + + /** + * Delete the record. + * @param TActiveRecord record to be deleted. + * @return int number of rows affected. + */ + public function delete(TActiveRecord $record) + { + return $this->getCommand($record)->deleteByPk($this->getPrimaryKeyValues($record)); + } + + protected function getPrimaryKeyValues(TActiveRecord $record) + { + $tableInfo = $this->getCommand($record)->getTableInfo(); + $primary=array(); + foreach($tableInfo->getColumns() as $name=>$column) + { + if($column->getIsPrimaryKey()) + $primary[$name] = $record->getColumnValue($name); + } + return $primary; + } + + /** + * Delete multiple records using primary keys. + * @param TActiveRecord finder instance. + * @return int number of rows deleted. + */ + public function deleteRecordsByPk(TActiveRecord $record, $keys) + { + return $this->getCommand($record)->deleteByPk($keys); + } + + /** + * Delete multiple records by criteria. + * @param TActiveRecord active record finder instance. + * @param TActiveRecordCriteria search criteria + * @return int number of records. + */ + public function deleteRecordsByCriteria(TActiveRecord $record, $criteria) + { + return $this->getCommand($record)->delete($criteria); + } + + /** + * Raise the corresponding command event, insert, update, delete or select. + * @param string command type + * @param TDbCommand sql command to be executed. + * @param TActiveRecord active record + * @param TActiveRecordCriteria data for the command. + */ + protected function raiseCommandEvent($event,$command,$record,$criteria) + { + if(!($criteria instanceof TSqlCriteria)) + $criteria = new TActiveRecordCriteria(null,$criteria); + $param = new TActiveRecordEventParameter($command,$record,$criteria); + $manager = $record->getRecordManager(); + $manager->{$event}($param); + $record->{$event}($param); + } +} + diff --git a/framework/Data/ActiveRecord/TActiveRecordManager.php b/framework/Data/ActiveRecord/TActiveRecordManager.php index ce14ac4d..9912e7ff 100644 --- a/framework/Data/ActiveRecord/TActiveRecordManager.php +++ b/framework/Data/ActiveRecord/TActiveRecordManager.php @@ -109,4 +109,3 @@ class TActiveRecordManager extends TComponent } -?> -- cgit v1.2.3