Tricks to reduce memory usage.
authorCameron Ball <c.ball1729@gmail.com>
Mon, 15 Dec 2014 11:24:19 +0000 (19:24 +0800)
committerCameron Ball <c.ball1729@gmail.com>
Mon, 15 Dec 2014 11:24:19 +0000 (19:24 +0800)
DataAccess/DataMapper/DataMapper.php
DataAccess/DataMapper/LazyLoadedEntities.php [new file with mode: 0644]

index 384627d..4936aaf 100644 (file)
@@ -7,6 +7,7 @@ use DataAccess\IDatabaseFactory;
 use DataAccess\DataMapper\IDataMapper;\r
 use DataAccess\Queries\IQueryBuilder;\r
 use DataAccess\DataMapper\Helpers\AbstractPopulationHelper;\r
+use DataAccess\DataMapper\LazyLoadedEntities;\r
 use ReflectionClass;\r
 \r
 class DataMapper implements IDataMapper\r
@@ -31,6 +32,12 @@ class DataMapper implements IDataMapper
         $rows = $statement->fetchAll();\r
         \r
         $entities = array();\r
+\r
+        if(count($rows) > 2)\r
+        {\r
+            //TODO: Factory?\r
+            return new LazyLoadedEntities($rows, $entityName, $this->_maps, $this->_db);\r
+        }\r
         \r
         foreach($rows as $row)\r
         {\r
@@ -48,7 +55,7 @@ class DataMapper implements IDataMapper
             $class->setId($row['id']);\r
             $entities[$row['id']] = $class;\r
         }\r
-        \r
+                \r
         return $entities;\r
     }\r
         \r
diff --git a/DataAccess/DataMapper/LazyLoadedEntities.php b/DataAccess/DataMapper/LazyLoadedEntities.php
new file mode 100644 (file)
index 0000000..724e635
--- /dev/null
@@ -0,0 +1,103 @@
+<?php\r
+\r
+namespace DataAccess\DataMapper;\r
+\r
+use DataAccess\DataMapper\Helpers\AbstractPopulationHelper;\r
+use ReflectionClass;\r
+use Iterator;\r
+\r
+class LazyLoadedEntities implements Iterator\r
+{\r
+    private $_maps;\r
+    private $_entityName;\r
+    private $_rows;\r
+    private $_rowIndex = 0;\r
+    private $_loadedEntitiesIndex = 0;\r
+    private $_loadedEntities = array();\r
+    private $_db;\r
+    \r
+    public function __construct(array $rows, $entityName, $maps, $db)\r
+    {\r
+        $this->_rows = $rows;\r
+        $this->_entityName = $entityName;\r
+        $this->_maps = $maps;\r
+        $this->_db = $db;\r
+    }\r
+    \r
+    public function current()\r
+    {\r
+        return $this->_loadedEntities[$this->_loadedEntitiesIndex];\r
+    }\r
+    \r
+    public function key()\r
+    {\r
+        return $this->_loadedEntitiesIndex;\r
+    }\r
+    \r
+    public function next()\r
+    {\r
+        $keys = array_keys($this->_loadedEntities);\r
+        $pos = array_search($this->_loadedEntitiesIndex, $keys);\r
+        if(isset($keys[$pos + 1]))\r
+        {\r
+            $this->_loadedEntitiesIndex = $keys[$pos+1];\r
+        } else {\r
+            $this->mapEntities(); //sets the loaded entites index\r
+        }\r
+    }\r
+    \r
+    public function rewind()\r
+    {\r
+        $this->_rowIndex = 0;\r
+        $this->mapEntities();\r
+    }\r
+    \r
+    public function valid()\r
+    {\r
+        //next will always load more entities when it runs out, therefore if\r
+        //we have an empty loadEntities array, it means there were no more and we are done.\r
+        if($this->_loadedEntities)\r
+        {\r
+            return true;\r
+        }\r
+        \r
+        return false;\r
+    }\r
+\r
+    //unsets the current entities array, and maps in the next 10\r
+    private function mapEntities()\r
+    {\r
+        $numToMap = 50;\r
+        $tick = 0;\r
+        \r
+        unset($this->_loadedEentities);\r
+        $this->_loadedEntities = array();\r
+        \r
+        $entityName = $this->_entityName;\r
+        for($i = $this->_rowIndex; $i<$this->_rowIndex+$numToMap; $i++)\r
+        {\r
+            if(isset($this->_rows[$i]))\r
+            {\r
+                $row = $this->_rows[$i];\r
+                $className = $this->_maps[$entityName]['class']; //the entity to instantiate and return\r
+                $constructors = AbstractPopulationHelper::getConstrutorArray($this->_maps, $entityName, $row, $this->_db);\r
+\r
+                if(count($constructors) == 0)\r
+                {\r
+                    $class = new $className;            \r
+                } else {\r
+                    $r = new ReflectionClass($className);\r
+                    $class = $r->newInstanceArgs($constructors);\r
+                }\r
+\r
+                $class->setId($row['id']);\r
+                $this->_loadedEntities[$row['id']] = $class;\r
+                \r
+                if($tick == 0) $this->_loadedEntitiesIndex = $row['id'];\r
+                $tick++;\r
+            }\r
+        }\r
+        \r
+        $this->_rowIndex += $numToMap;\r
+    }\r
+}
\ No newline at end of file