Tricks to reduce memory usage.
[rock.divinelegy.git] / DataAccess / DataMapper / LazyLoadedEntities.php
1 <?php
2
3 namespace DataAccess\DataMapper;
4
5 use DataAccess\DataMapper\Helpers\AbstractPopulationHelper;
6 use ReflectionClass;
7 use Iterator;
8
9 class LazyLoadedEntities implements Iterator
10 {
11 private $_maps;
12 private $_entityName;
13 private $_rows;
14 private $_rowIndex = 0;
15 private $_loadedEntitiesIndex = 0;
16 private $_loadedEntities = array();
17 private $_db;
18
19 public function __construct(array $rows, $entityName, $maps, $db)
20 {
21 $this->_rows = $rows;
22 $this->_entityName = $entityName;
23 $this->_maps = $maps;
24 $this->_db = $db;
25 }
26
27 public function current()
28 {
29 return $this->_loadedEntities[$this->_loadedEntitiesIndex];
30 }
31
32 public function key()
33 {
34 return $this->_loadedEntitiesIndex;
35 }
36
37 public function next()
38 {
39 $keys = array_keys($this->_loadedEntities);
40 $pos = array_search($this->_loadedEntitiesIndex, $keys);
41 if(isset($keys[$pos + 1]))
42 {
43 $this->_loadedEntitiesIndex = $keys[$pos+1];
44 } else {
45 $this->mapEntities(); //sets the loaded entites index
46 }
47 }
48
49 public function rewind()
50 {
51 $this->_rowIndex = 0;
52 $this->mapEntities();
53 }
54
55 public function valid()
56 {
57 //next will always load more entities when it runs out, therefore if
58 //we have an empty loadEntities array, it means there were no more and we are done.
59 if($this->_loadedEntities)
60 {
61 return true;
62 }
63
64 return false;
65 }
66
67 //unsets the current entities array, and maps in the next 10
68 private function mapEntities()
69 {
70 $numToMap = 50;
71 $tick = 0;
72
73 unset($this->_loadedEentities);
74 $this->_loadedEntities = array();
75
76 $entityName = $this->_entityName;
77 for($i = $this->_rowIndex; $i<$this->_rowIndex+$numToMap; $i++)
78 {
79 if(isset($this->_rows[$i]))
80 {
81 $row = $this->_rows[$i];
82 $className = $this->_maps[$entityName]['class']; //the entity to instantiate and return
83 $constructors = AbstractPopulationHelper::getConstrutorArray($this->_maps, $entityName, $row, $this->_db);
84
85 if(count($constructors) == 0)
86 {
87 $class = new $className;
88 } else {
89 $r = new ReflectionClass($className);
90 $class = $r->newInstanceArgs($constructors);
91 }
92
93 $class->setId($row['id']);
94 $this->_loadedEntities[$row['id']] = $class;
95
96 if($tick == 0) $this->_loadedEntitiesIndex = $row['id'];
97 $tick++;
98 }
99 }
100
101 $this->_rowIndex += $numToMap;
102 }
103 }