0

I am using Datamapper and want to join all columns of a related table (1:1 relationship) in the result set. Hence, my code reads as follows:

$p = new Project();
$arrAll = $p->where("id <", 100)->where_related('outboundform', 'reference_type', 'project')->include_related('outboundform')->get()->all_to_array();
print_r($arrAll);

The query works, but no column of table 'outboundform' shows up in the result, they get completely ignored!! I just checked and the generated SQL reads:

SELECT `project` . * , `outboundform`.`id` AS outboundform_id, `outboundform`.`reference_type` AS outboundform_reference_type, `outboundform`.`reference_id` AS outboundform_reference_id, `outboundform`.`created` AS outboundform_created, `outboundform`.`updated` AS outboundform_updated, `outboundform`.`v1` AS outboundform_v1, `outboundform`.`v2` AS outboundform_v2, `outboundform`.`v3` AS outboundform_v3, `outboundform`.`v4` AS outboundform_v4, `outboundform`.`v5` AS outboundform_v5 FROM (`project`) LEFT OUTER JOIN `outboundform` outboundform ON `project`.`id` = `outboundform`.`reference_id` WHERE `project`.`id` <100 AND `outboundform`.`reference_type` = 'project' LIMIT 0 , 30

which is OK and gives me the correct result when executed. What's Datamappers problem here? Why is it not return the full amount of columns?

hofimax
  • 249
  • 1
  • 3
  • 10

1 Answers1

0

The related outboundform row's properties should be accessible in the result object prefixed with the relation's name. So the id becomes outboundform_id, the reference_type becomes outboundform_reference_type and so on.

The problem is that all_to_array() doesn't transfer those to the array version of results. If you want to include them you will have to explicitly list them:

$arrAll = $p->/* snip */->all_to_array(array('id', 'name', 'outboundform_id', 'outboundform_reference_type')); // Project fields and outboundform fields too

If you have an instance of any model, you can get the list of fields by the $instance->fields property of that model (from the database table), and use those to create the list for the all_to_array call by creating prefixed names for the included relation.

Alternatively, if you only need the [] way of accessing fields, you can implement ArrayAccess interface like this:

class DataMapper2 extends DataMapper implements ArrayAccess
{ 
    public function offsetSet($offset, $value)
    {
        if (is_null($offset)) {
            throw new ErrorException('model instances doesn\'t support pushing new fields');
        } else {
            $this->{$offset} = $value;
        }
    }
    public function offsetExists($offset)
    {
        return isset($this->{$offset});
    }
    public function offsetUnset($offset)
    {
        unset($this->{$offset});
    }
    public function offsetGet($offset)
    {
        return isset($this->{$offset}) ? $this->{$offset} : null;
    }
}
complex857
  • 20,425
  • 6
  • 51
  • 54
  • thanks for your response. I am currently accessing the object to get the fields, just as you proposed. your suggestion of using $instance->fields does not work though, as it does NOT contain the joined fields. $instance->outboundform->field DOES contain the fields. but I perceive it as too much a hack to use it. Overall, I think it should be classified as a bug. – hofimax Nov 21 '12 at 22:24
  • Yes, the `$instance->field` will only hold the filed names extracted from the dbschema by the library, i meant that you would have to manually create the prefixed versions from a `outboundform` instance and merge those with the project's fields. Alternatively implement the `ArrayAccess` interface on `DataMapper` objects so you get `[]` access without making the objects into arrays. – complex857 Nov 22 '12 at 05:40
  • fields define the columns in the models table, not the columns in the query result. – WanWizard Jan 21 '13 at 17:39