I have done somthing like this, and yes I have created a model_row class to pass all data to in a array_walk style:
if ($qry = $this->db->get()) {
$res = $qry->result();
return $this->_instantiateRows($res);
}
Function _instantiateRows():
/**
* Get the row class name
* Checks if a class exists with the model name _Row
* @return string
*/
private function _getRowClass() {
$modelName = get_class($this);
return class_exists($modelName.'_Row') ? $modelName.'_Row' : 'Model_Row';
}
/**
* Formats results into model row classes
* @param array $results
* @return array
*/
protected function _instantiateRows($results) {
$rowClass = $this->_getRowClass();
$self = $this;
array_walk($results,function(&$row,$k) use ($rowClass, $self) {
$row = new $rowClass($row,$self,$k);
});
return $results;
}
Then a row class:
/**
* Model row class
* Acts as a baseclass and a fallback class for database rows
* Implements standard methods, for saving, getting the ID, and setting field
* values.
* @property $_model MY_Model
* @property $_key Original Array key
* @property $_ID_FIELD name of the id field
*/
class Model_Row
{
protected $_isNew = True;
protected $_model = False;
protected $_key = False;
protected $_ID_FIELD = 'id';
protected $_ID_ORIGINAL = False;
/**
* C'tor
* Sets up the object with data from the row
* @param object $data
* @param object $model
* @param int $key
* @param string $id_field
*/
public function __construct($data,$model,$key=False) {
$this->_key = $key;
// If no key is specified then it must be new / Not from database
if ($this->_key !== False)
$this->_isNew = False;
$data = (array)$data;
$this->_model = $model;
$this->_ID_FIELD = $model->idField;
$this->set($data);
// Ensure ID Field is set.
$idF = $this->_ID_FIELD;
if (!isset($this->$idF))
$this->$idF = null;
}
/**
* Get the ID field
* ID Field could be named differently for each model, this is an easy
* shortcut to it.
* @param string $setTo - set the id to this value
* @return string
*/
public function id($setTo=False) {
$idF = $this->_ID_FIELD;
if ($setTo !== False) {
if ($this->_ID_ORIGINAL === False && !$this->_isNew)
$this->_ID_ORIGINAL = $this->$idF;
$this->set($idF,$setTo);
}
return $this->$idF !== null ? (string)$this->$idF : False;
}
/**
* Save this row
* @return bool
*/
public function save() {
$wheres = array();
if (!$this->_isNew) {
$idF = $this->_ID_FIELD;
$wheres[$idF] = $this->_ID_ORIGINAL ?: $this->id();
}
$res = $this->_model->set($this,$wheres);
if ($this->id() === False)
$this->id($this->_model->insertID());
// Reset the original id field
$this->_ID_ORIGINAL = False;
$this->_isNew = False;
if ($res)
return $this;
return False;
}
/**
* Set object properties
* can be passed by array field => value
* @param mixed $field
* @param mixed $value
* @return null
*/
public function set($field,$value=False) {
if ((is_array($field) || is_object($field)) && $value === False) {
if (is_object($field))
$field = (array)$field;
foreach($field as $f => $v)
$this->set($f,$v);
}
else {
if (method_exists($this, 'set_'.$field))
call_user_func(array($this,'set_'.$field), $value);
else
$this->$field = $value;
}
}
}
The point of the _getRowClass
is to check for a class called model_name_row
if this exists, then instantiate the data to this class, otherwise fall back to the baseclass model_row
There are some other things your model will need too, because the row class will be passed the model, so your model will need a public $idField='id'
, and then this function can be usefull on your model:
/**
* Create a new record using the model row class
* @param mixed $data
* @return Model_Row
*/
public function newRow($data=array()) {
$rowClass = $this->_getRowClass();
return new $rowClass($data,$this);
}
So you can do $newRow = $this->Model->newRow($data)
which will create a new row, then can call $newRow->save()
and other methods if set...
* EDIT
Also to point out, I use $this->_model->set($this, $wheres)
on the row class, this is because I have defined a baseclass with a public setter:
/**
* Setter
* @param mixed $data object or array
* @param mixed $wheres object or array query
* @return bool
*/
public function set($data,$wheres=array()) {
if (!$this->checkTableSet())
return False;
if (empty($wheres)) {
return $this->db->insert($this->table,$data);
}
else {
$this->db->where($wheres);
return $this->db->update($this->table,$data);
}
}
$this->table
is a model variable with the table name, e.g. protected $table='users';
and the function checkTableSet()
simply checks whether this has been set and not empty..