An active record creates an object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data. Active record objects are stateful, this is main difference between the TActiveRecord implementation and the TTableGateway implementation. The essence of an Active Record is an object model of the domain (e.g. products, items) that incorporates both behavior and data in which the classes match very closely the record structure of an underlying database. Each Active Record is responsible for saving and loading to the database and also for any domain logic that acts on the data. The Active Record provides methods that do the following: 1. Construct an instance of the Active Record from a SQL result set row. 2. Construct a new instance for later insertion into the table. 3. Finder methods to wrap commonly used SQL queries and return Active Record objects. 4. Update the database and insert into it the data in the Active Record. Example: class UserRecord extends TActiveRecord { const TABLE='users'; //optional table name. public $username; //corresponds to the fieldname in the table public $email; returns active record finder instance public static function finder($className=__CLASS__) { return parent::finder($className); } } create a connection and give it to the ActiveRecord manager. $dsn = 'pgsql:host=localhost;dbname=test'; $conn = new TDbConnection($dsn, 'dbuser','dbpass'); TActiveRecordManager::getInstance()->setDbConnection($conn); load the user record with username (primary key) 'admin'. $user = UserRecord::finder()->findByPk('admin'); $user->email = 'admin@example.org'; $user->save(); //update the 'admin' record. Since v3.1.1, TActiveRecord starts to support column mapping. The physical column names (defined in database) can be mapped to logical column names (defined in active classes as public properties.) To use this feature, declare a static class variable COLUMN_MAPPING like the following: class UserRecord extends TActiveRecord { const TABLE='users'; public static $COLUMN_MAPPING=array ( 'user_id'=>'username', 'email_address'=>'email', ); public $username; public $email; } In the above, the 'users' table consists of 'user_id' and 'email_address' columns, while the UserRecord class declares 'username' and 'email' properties. By using column mapping, we can regularize the naming convention of column names in active record. Since v3.1.2, TActiveRecord enhanced its support to access of foreign objects. By declaring a public static variable RELATIONS like the following, one can access the corresponding foreign objects easily: class UserRecord extends TActiveRecord { const TABLE='users'; public static $RELATIONS=array ( 'department'=>array(self::BELONGS_TO, 'DepartmentRecord', 'department_id'), 'contacts'=>array(self::HAS_MANY, 'ContactRecord', 'user_id'), ); } In the above, the users table is related with departments table (represented by DepartmentRecord) and contacts table (represented by ContactRecord). Now, given a UserRecord instance $user, one can access its department and contacts simply by: $user->department and $user->contacts. No explicit data fetching is needed. Internally, the foreign objects are fetched in a lazy way, which avoids unnecessary overhead if the foreign objects are not accessed at all. Since v3.1.2, new events OnInsert, OnUpdate and OnDelete are available. The event OnInsert, OnUpdate and OnDelete methods are executed before inserting, updating, and deleting the current record, respectively. You may override these methods; a TActiveRecordChangeEventParameter parameter is passed to these methods. The property {@link TActiveRecordChangeEventParameter::setIsValid IsValid} of the parameter can be set to false to prevent the change action to be executed. This can be used, for example, to validate the record before the action is executed. For example, in the following the password property is hashed before a new record is inserted. class UserRecord extends TActiveRecord { function OnInsert($param) { parent method should be called to raise the event parent::OnInsert($param); $this->nounce = md5(time()); $this->password = md5($this->password.$this->nounce); } } Since v3.1.3 you can also define a method that returns the table name. class UserRecord extends TActiveRecord { public function table() { return 'users'; } }
Since: 3.1
Inheritance: extends Prado\TComponent
Beispiel #1
0
 /**
  * Apply result mapping.
  * @param array a result set row retrieved from the database
  * @param object the result object, will create if necessary.
  * @return object the result filled with data, null if not filled.
  */
 protected function applyResultMap($row, &$resultObject = null)
 {
     if ($row === false) {
         return null;
     }
     $resultMapName = $this->_statement->getResultMap();
     $resultClass = $this->_statement->getResultClass();
     $obj = null;
     if ($this->getManager()->getResultMaps()->contains($resultMapName)) {
         $obj = $this->fillResultMap($resultMapName, $row, null, $resultObject);
     } else {
         if (strlen($resultClass) > 0) {
             $obj = $this->fillResultClass($resultClass, $row, $resultObject);
         } else {
             $obj = $this->fillDefaultResultMap(null, $row, $resultObject);
         }
     }
     if (class_exists('TActiveRecord', false) && $obj instanceof TActiveRecord) {
         //Create a new clean active record.
         $obj = TActiveRecord::createRecord(get_class($obj), $obj);
     }
     return $obj;
 }
 /**
  * Returns foreign keys in $fromRecord with source column names as key
  * and foreign column names in the corresponding $matchesRecord as value.
  * The method returns the first matching foreign key between these 2 records.
  * @param TActiveRecord $fromRecord
  * @param TActiveRecord $matchesRecord
  * @return array foreign keys with source column names as key and foreign column names as value.
  */
 protected function findForeignKeys($from, $matchesRecord, $loose = false)
 {
     $gateway = $matchesRecord->getRecordGateway();
     $recordTableInfo = $gateway->getRecordTableInfo($matchesRecord);
     $matchingTableName = strtolower($recordTableInfo->getTableName());
     $matchingFullTableName = strtolower($recordTableInfo->getTableFullName());
     $tableInfo = $from;
     if ($from instanceof TActiveRecord) {
         $tableInfo = $gateway->getRecordTableInfo($from);
     }
     //find first non-empty FK
     foreach ($tableInfo->getForeignKeys() as $fkeys) {
         $fkTable = strtolower($fkeys['table']);
         if ($fkTable === $matchingTableName || $fkTable === $matchingFullTableName) {
             $hasFkField = !$loose && $this->getContext()->hasFkField();
             $key = $hasFkField ? $this->getFkFields($fkeys['keys']) : $fkeys['keys'];
             if (!empty($key)) {
                 return $key;
             }
         }
     }
     //none found
     $matching = $gateway->getRecordTableInfo($matchesRecord)->getTableFullName();
     throw new TActiveRecordException('ar_relations_missing_fk', $tableInfo->getTableFullName(), $matching);
 }
Beispiel #3
0
 /**
  * @return TActiveRecord Active Record finder instance
  */
 protected function getRecordFinder()
 {
     return TActiveRecord::finder($this->getRecordClass());
 }
 /**
  * @return TActiveRecord corresponding relationship foreign object finder instance.
  */
 public function getForeignRecordFinder()
 {
     return TActiveRecord::finder($this->getForeignRecordClass());
 }
 /**
  * @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());
         $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];
 }
 /**
  * @param string active record class name.
  * @param array row data
  * @param array foreign key column names
  * @return TActiveRecord
  */
 protected function createFkObject($type, $row, $foreignKeys)
 {
     $obj = TActiveRecord::createRecord($type, $row);
     if (count($this->_association_columns) > 0) {
         $i = 0;
         foreach ($foreignKeys as $ref => $fk) {
             $obj->setColumnValue($ref, $row[$this->_association_columns[$i++]]);
         }
     }
     return $obj;
 }