As U know, using ActiveRecord is very handy, but useless when we want to databind result from TActiveRecord to any TDataBoundControl like TDataList, TDataGrid, TRepeater, TDropDownList, etc. because ActiveRecord can't be source for those controls.
But there is a light in a tunel

First what we must to do is to extend our ActiveRecord class
<?php
PRADO::using('System.Data.ActiveRecord.TActiveRecord');
class TOurActiveRecord extends TActiveRecord {
public function onInit($param) {
parent::onInit($param);
$this->clearData();
}
/**
* Our activeRecord data as array()
*
* @var array
* @access private
*/
protected static $_data;
/**
* Tell us thet result should be populated as object or as array
*
* @var boolean
* @access protected
* @static
*/
protected static $_populateAsObject = true;
/**
* Returns data
*
* @return array
* @access protected
*/
private function getData() {
return TOurActiveRecord::$_data;
}
/**
* Save data
*
* @param array $value
* @access protected
*/
private function setData ($value) {
TOurActiveRecord::$_data = TPropertyValue::ensureArray($value);
}
/**
* Our main and most important extension of standatd populateObject implementation
*
* @param string $type
* @param array $data
* @return mixed
*/
protected function populateObject($type, $data) {
$this->setData($data);
if ($this->getPopulateAsObj() === true) {
return parent::populateObject($type,$data);
}
else {
return $data;
}
}
/**
* Ustawia znacznik zwracanego obiektu
*
* @param boolea $value
* @access public
*/
public function setPopulateAsObj($value) {
TOurActiveRecord::$_populateAsObject = TPropertyValue::ensureBoolean($value);
}
/**
*Setting out flag: if true, activeRecord will return data as Object when false as array
*
* @return boolean
* @access public
*/
public function getPopulateAsObj() {
return TOurActiveRecord::$_populateAsObject;
}
/**
* Return our data as array()
*
* @return array
* @access public
*/
public function asArray() {
return TOurActiveRecord::$_data;
}
/**
* Clear data, to avoid situation, when ActiveRecord returns null and we still have data from last object
*
* @return array
* @access public
*/
public static function clearData() {
TOurActiveRecord::$_data = null;
}
}
?>
Now we can use our extended ActiveRecord class as a base class for all ActiveRecords. But this is not all what we must to do. Second thing is simple extension for every ActiveRecord class e.g. UserRecord, which I put below:
<?php
PRADO::using('Application.Path_to.TOurActiveRecord');
class UserRecord extends TOurActiveRecord {
public $user_id;
public $username;
public $email;
public $pass;
public static $_tablename="my_user_database_table_name";
/**
* This is main and most important extension, without this extensions made in TOurActiveRecord are useless!
* Setting populateAsObject property we decide what should be returned: object (true) or array (false)
* @param boolean $populateAsObject
* @return object
*/
public static function finder($populateAsObject = true) {
self::$_populateAsObject = TPropertyValue::ensureBoolean($populateAsObject);
return self::getRecordFinder('UserRecord');
}
}
?>
Now we can use our UserRecord results as DataSource for TDataBoundControls
public function onLoad($param) {
parent::onLoad($param);
if ($this->IsPostBack) {
$id = $this->Request['id']; //id received by Request
$users = UserRecord::finder(false)->findByPk($id); //ActiveRecord usage
$repeater->DataSource = $users; //voila!
$repeater->dataBind(); //works! adm everybody are happy :)
}
}
I think this approach is much better than declaring SqlMap for such simple query or using sql statement in CreateCommand(). Why? Because we can use full Active Record support for findBy, findAll findByPks and this is huge profit in code readability and really helps when refactoring is needed