Skip to content

Commit

Permalink
Implemented hydration for eager loaded has many records
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzo committed Sep 12, 2013
1 parent dd7d6e1 commit 0e651e0
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 20 deletions.
11 changes: 8 additions & 3 deletions lib/Cake/ORM/Association/ExternalAssociationTrait.php
Expand Up @@ -170,10 +170,15 @@ protected function _buildQuery($options) {
$options['conditions'] = array_merge($this->conditions(), $options['conditions']);
$key = $this->_linkField($options);

$filter = ($options['strategy'] == parent::STRATEGY_SUBQUERY) ?
$this->_buildSubquery($options['query'], $key) : $options['keys'];
$filter = $options['keys'];
if ($options['strategy'] === parent::STRATEGY_SUBQUERY) {
$filter = $this->_buildSubquery($options['query'], $key);
}

$fetchQuery = $target->find('all')->where($options['conditions']);
$fetchQuery = $target
->find('all')
->where($options['conditions'])
->hydrate($options['query']->hydrate());
$fetchQuery = $this->_addFilteringCondition($fetchQuery, $key, $filter);

if (!empty($options['fields'])) {
Expand Down
26 changes: 20 additions & 6 deletions lib/Cake/ORM/Entity.php
Expand Up @@ -6,6 +6,14 @@ class Entity implements \ArrayAccess {

protected $_properties = [];

public function __get($property) {
return $this->get($property);
}

public function __set($property, $value) {
$this->set([$property => $value]);
}

public function set($properties = [], $useSetters = true) {
if (!$useSetters) {
$this->_properties = $properties + $this->_properties;
Expand All @@ -31,12 +39,18 @@ public function get($property) {
return $value;
}

public function __get($property) {
return $this->get($property);
}

public function __set($property, $value) {
$this->set([$property => $value]);
/**
* Returns an array with all the properties that have been set
* to this entity
*
* @return array
*/
public function toArray() {
$result = [];
foreach ($this->_properties as $property => $value) {
$result[$property] = $this->get($property);
}
return $result;
}

/**
Expand Down
35 changes: 24 additions & 11 deletions lib/Cake/ORM/Query.php
Expand Up @@ -793,6 +793,29 @@ protected function _addJoin($association, $options) {
* @return CallbackStatement $statement modified statement with extra loaders
*/
protected function _eagerLoad($statement) {
$keys = $this->_collectKeys($statement);
foreach ($this->_loadEagerly as $association => $meta) {
$contain = $meta['associations'];
$alias = $meta['instance']->source()->alias();
$keys = isset($keys[$alias]) ? $keys[$alias] : null;
$f = $meta['instance']->eagerLoader(
$meta['config'] + ['query' => $this, 'contain' => $contain, 'keys' => $keys]
);
$statement = new CallbackStatement($statement, $this->connection()->driver(), $f);
}

return $statement;
}

/**
* Helper function used to return the keys from the query records that will be used
* to eagerly load associations.
*
*
* @param BufferedStatement $statement
* @return array
*/
protected function _collectKeys($statement) {
$collectKeys = [];
foreach ($this->_loadEagerly as $association => $meta) {
$source = $meta['instance']->source();
Expand All @@ -813,17 +836,7 @@ protected function _eagerLoad($statement) {
$statement->rewind();
}

foreach ($this->_loadEagerly as $association => $meta) {
$contain = $meta['associations'];
$alias = $meta['instance']->source()->alias();
$keys = isset($keys[$alias]) ? $keys[$alias] : null;
$f = $meta['instance']->eagerLoader(
$meta['config'] + ['query' => $this, 'contain' => $contain, 'keys' => $keys]
);
$statement = new CallbackStatement($statement, $this->connection()->driver(), $f);
}

return $statement;
return $keys;
}

/**
Expand Down
43 changes: 43 additions & 0 deletions lib/Cake/Test/TestCase/ORM/QueryTest.php
Expand Up @@ -1113,4 +1113,47 @@ public function testHydrateSimple() {
$this->assertEquals('Y', $first->published);
}

/**
* Tests that has many results are also hydrated correctly
*
* @return void
*/
public function testHydrateWithHasMany() {
$this->_createTables();

$table = Table::build('author', ['connection' => $this->connection]);
Table::build('article', ['connection' => $this->connection]);
$table->hasMany('article', [
'property' => 'articles',
'sort' => ['article.id' => 'asc']
]);
$query = new Query($this->connection, $table);
$results = $query->select()
->contain('article')
->hydrate(true)
->toArray();

$first = $results[0];
foreach ($first->articles as $r) {
$this->assertInstanceOf('\Cake\ORM\Entity', $r);
}

$this->assertCount(2, $first->articles);
$expected = [
'id' => 1,
'title' => 'First Article',
'body' => 'First Article Body',
'author_id' => 1,
'published' => 'Y',
];
$this->assertEquals($expected, $first->articles[0]->toArray());
$expected = [
'id' => 3,
'title' => 'Third Article',
'author_id' => 1,
'body' => 'Third Article Body',
'published' => 'Y',
];
$this->assertEquals($expected, $first->articles[1]->toArray());
}
}

0 comments on commit 0e651e0

Please sign in to comment.