@OverZealous - Cool stuff!.. it seems like we’re both working similarly on enhancing datamapper to build more effective queries and allow for more relevant data to be available upon getting a datamap.
in my last post i tried creating a join_related function, although in only joined one field from a related item, so i have it joining every field now and inserting it into the related datamaps’ object fields. Although i believe very much in using aliasing, so that where clauses don’t need to explicitly specify a table, and also to prevent name collisions.
before, i had it set up so it needed to be called explicitly in the controller, but now i have it called in the get() method automatically..
// in method get()..
$this->total_count = $this->db->count_all($this->table);
// Clear this object to make way for new data
$this->_clear(TRUE);
if( ! $this->table_joined)
{
$related = array_merge($this->has_one, $this->has_many);
$this->join_related($related);
}
// Get by built up query
$query = $this->db->get($this->table, $limit, $offset);..and have it auto-assign the values to each related object (db values for has_one, count for has_many)...
if ($query->num_rows() > 0)
{
$this->record_count = $query->num_rows();
// Populate all with records as objects
//$this->all = $this->_to_object($query->result(), $this->model, $this->fields);
$this->all = $this->_to_object($query->result_array(), $this->model, $this->fields);
$row = $query->row_array();
foreach($this->has_one as $related)
{
if(is_object($this->{$related}))
{
$fields = $this->{$related}->fields;
foreach($fields as $field)
{
$lookup = $related.'_'.$field;
if(array_key_exists($lookup, $row))
{
$this->{$related}->{$field} = $row[$lookup];
}
}
}
}
foreach($this->has_many as $related)
{
if(is_object($this->{$related}))
{
$lookup = $related.'_count';
if(array_key_exists($lookup, $row) && ! empty($row[$lookup]))
{
$this->{$related}->record_count = $row[$lookup];
}
else
{
$this->{$related}->record_count = 0;
}
}
}
foreach($this->fields as $field)
{
if(array_key_exists($field, $row))
{
$this->{$field} = $row[$field];
}
}
}so now the query is compressed into one, and all related objects’ fields are populated as if they had get() called on them explicitly.
I also have two additional bits of data, total_count and result_count, auto populated in the datamap. so $user->total_count returns a count of all the users in its table, and $user->result_count returns the number of rows returned in the query..
There was one bump, however, and that was in order for all the records of the datamap to have their related objects populated in the ->all array, i similarly adjusted the _to_object method..
function _to_object($result_array, $model, $fields)
{
$items = array();
foreach ($result_array as $row_array)
{
$item = new $model;
foreach($item->has_one as $related)
{
if(is_object($item->{$related}))
{
$related_fields = $item->{$related}->fields;
foreach($related_fields as $related_field)
{
$lookup = $related.'_'.$related_field;
if(array_key_exists($lookup, $row_array))
{
$item->{$related}->{$related_field} = $row_array[$lookup];
}
else
{
$item->{$related}->{$related_field} = NULL;
}
}
}
}
foreach($item->has_many as $related)
{
if(is_object($item->{$related}))
{
$lookup = $related.'_count';
if(array_key_exists($lookup, $row_array) && ! empty($row_array[$lookup]))
{
$item->{$related}->result_count = $row_array[$lookup];
}
else
{
$item->{$related}->result_count = 0;
}
}
}
foreach($fields as $field)
{
if(array_key_exists($field, $row_array))
{
$item->{$field} = $row_array[$field];
}
else
{
$item->{$field} = NULL;
}
}
array_push($items, $item);
}
return $items;
}so, now it works with the efficient SQL, but with the same kind of ease of use originally designed in DataMapper..
//controller users
$user = new User();
$user->get();
// multiple users, one query
foreach($user->all as $u)
{
echo $u->username .' is a '.$u->userclass->name.' with a rank of '.$u->userclass->rank.' and belongs to '.$u->usergroup->name . br();
if($u->document->result_count > 0)
{
echo $u->username .' also has '.$u->document->result_count.' documents.'.br();
}
}still have to edit the _to_array method to spit out a multi-dimensional array containing the related information
as far as where searches.. i built up a prototype of where_related and i’m still working on that.. also for ‘many’ searches i want to create a where_related_count()
the other AR methods will also need attention (sort by alias, etc).. but i wont be able to do an entire overhaul of DM until i have time..
CC