Skip to content

Commit

Permalink
#36 - Eager loading
Browse files Browse the repository at this point in the history
  • Loading branch information
TRPB committed Dec 22, 2017
1 parent b310fed commit e561012
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 25 deletions.
1 change: 1 addition & 0 deletions maphper/datasource/mysqladapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,5 @@ public function optimiseColumns($table) {
//Sometimes a second pass is needed, if a column has gone from varchar -> int(11) a better int type may be needed
if ($runAgain) $this->optimiseColumns($table);
}

}
36 changes: 18 additions & 18 deletions maphper/iterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,30 @@
namespace Maphper;

class Iterator implements \Iterator {
private $array;
private $pk;
private $iterator = 0;
private $array;
private $pk;
private $iterator = 0;

public function __construct(array $array, $pk) {
$this->array = $array;
$this->pk = $pk;
}
public function __construct(array $array, $pk) {
$this->array = $array;
$this->pk = $pk;
}

public function current() {
public function current() {
return $this->array[$this->iterator];
}

public function key() {
if (count($this->pk) == 1) {
$pk = end($this->pk);
return $this->array[$this->iterator]->$pk;
}
else {
$current = $this->current();
return array_map(function($pkName) use ($current) {
return $current->$pkName;
}, $this->pk);
}
if (count($this->pk) == 1) {
$pk = end($this->pk);
return $this->array[$this->iterator]->$pk;
}
else {
$current = $this->current();
return array_map(function($pkName) use ($current) {
return $current->$pkName;
}, $this->pk);
}
}

public function next() {
Expand Down
10 changes: 6 additions & 4 deletions maphper/maphper.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ private function getResults() {
$results = $this->dataSource->findByField($this->settings['filter'],
['order' => $this->settings['sort'], 'limit' => $this->settings['limit'], 'offset' => $this->settings['offset'] ]);

$siblings = new \ArrayObject();

$results = array_map([$this, 'createNew'], $results);
$results = array_map([$this, 'wrap'], $results);
array_walk($results, [$this, 'wrap'], $siblings);

return $results;
}
Expand Down Expand Up @@ -140,16 +142,16 @@ private function processDates($obj) {
return $injector->replaceDates($obj);
}

private function wrap($object) {
private function wrap($object, $key = null, $siblings = null) {
//see if any relations need overwriting
foreach ($this->relations as $name => $relation) {
if (isset($object->$name) && !($object->$name instanceof \Maphper\Relation) ) {
//After overwriting the relation, does the parent object ($object) need overwriting as well?
if ($relation->overwrite($object, $object->$name)) $this[] = $object;

}

$object->$name = $relation->getData($object);
$object->$name = $relation->getData($object, $siblings);
//var_dump($siblings);
}
return $object;
}
Expand Down
40 changes: 37 additions & 3 deletions maphper/relation/one.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class One implements \Maphper\Relation {
private $parentObject;
private $criteria = [];
private $data;
private $siblings = [];

public function __construct(\Maphper\Maphper $mapper, $parentField, $localField, array $criteria = []) {
$this->mapper = $mapper;
Expand All @@ -15,10 +16,14 @@ public function __construct(\Maphper\Maphper $mapper, $parentField, $localField,
$this->criteria = $criteria;
}

public function getData($parentObject) {
public function getData($parentObject, &$siblings = null) {
//Don't actually fetch the related data, return an instance of $this that will lazy load data when __get is called
$clone = clone $this;
$clone->parentObject = $parentObject;
$siblings[] = $clone;
$clone->siblings = $siblings;

// var_dump($siblings);
return $clone;
}

Expand All @@ -27,12 +32,41 @@ private function lazyLoad() {

if ($this->parentObject == null) throw new \Exception('Error, no object set');

if ($this->criteria) $this->data = $this->mapper->filter($this->criteria)->filter([$this->localField => $this->parentObject->{$this->parentField}])->item(0);
else $this->data = $this->mapper->filter([$this->localField => $this->parentObject->{$this->parentField}])->item(0);
$this->eagerLoad();

}
return $this->data;
}

private function eagerLoad() {
$recordsToLoad = [];
//Get a list of records by FK to eager load
foreach ($this->siblings as $sibling) {
$recordsToLoad[] = $sibling->parentObject->{$sibling->parentField};
}

$recordsToLoad = array_unique($recordsToLoad);
//Fetch the results so they're in the cache for the corresponding maphper object
if ($this->criteria) $results = $this->mapper->filter($this->criteira)->filter([$this->localField => $recordsToLoad]);
else $results = $this->mapper->filter([$this->localField => $recordsToLoad]);

$cache = [];
foreach ($results as $result) {
$cache[$result->{$this->localField}] = $result;
}

foreach ($this->siblings as $sibling) {
$sibling->data = $cache[$sibling->parentObject->{$this->parentField}];
}
/*
foreach ($this->siblings as $sibling) {
if ($sibling->criteria) $sibling->data = $sibling->mapper->filter($sibling->criteria)->filter([$sibling->localField => $sibling->parentObject->{$sibling->parentField}])->item(0);
else $sibling->data = $sibling->mapper->filter([$sibling->localField => $sibling->parentObject->{$this->parentField}])->item(0);
}
*/

}

public function __call($func, array $args = []) {
if ($this->lazyLoad() == null) return '';
return call_user_func_array([$this->lazyLoad(), $func], $args);
Expand Down
20 changes: 20 additions & 0 deletions tests/MySqlDatabaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1132,4 +1132,24 @@ public function testInsertNoEditModeNoDefaultValue() {


}

/*
//Need some way of asserting this happens
public function testEagerLoad() {
$this->populateBlogsAuthors();
$blogs = new \Maphper\Maphper($this->getDataSource('blog', 'id', ['editmode' => true]));
$authors = new \Maphper\Maphper($this->getDataSource('author'));
$blogs->addRelation('author', new \Maphper\Relation\One($authors, 'authorId', 'id'));
//This should issue two queries
foreach ($blogs as $blog) {
echo 'iteration';
$aName = $blog->author->name;
}
}
*/
}

0 comments on commit e561012

Please sign in to comment.