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';
}
}