Permalink
Browse files

Preload now supports abbreviations and closure.

  • Loading branch information...
1 parent ef4d846 commit 060c19560779af5c08cfdef4a33851f2009ff18f @gabordemooij committed Nov 30, 2012
Showing with 141 additions and 9 deletions.
  1. +2 −2 RedBean/Facade.php
  2. +36 −6 RedBean/OODB.php
  3. +103 −1 testing/RedUNIT/Base/Preloading.php
View
@@ -1104,8 +1104,8 @@ public static function getRedBean() {
* @param array $beans beans
* @param array $types types to load
*/
- public static function preload($beans,$types) {
- return self::$redbean->preload($beans,$types);
+ public static function preload($beans,$types,$closure = null) {
+ return self::$redbean->preload($beans,$types,$closure);
}
}
View
@@ -890,13 +890,32 @@ public function setDepList($dep) {
*
* Usage: $redbean->preload($books,array('coauthor'=>'author'));
*
+ * Usage for nested beans:
+ *
+ * $redbean->preload($texts,array('page','page.book','page.book.author'));
+ *
+ * preloads pages, books and authors.
+ * You may also use a shortcut here:
+ *
+ * $redbean->preload($texts,array('page','*.book','*.author'));
+ *
+ * Can also load preload lists:
+ *
+ * $redbean->preload($books,'ownPage'=>'page','*.ownText'=>'text');
+ *
* @param array $beans beans
* @param array $types types to load
*/
- public function preload($beans, $types) {
+ public function preload($beans, $types, $closure = null) {
+ if (is_string($types)) $types = explode(',',$types);
+ $oldFields = array(); $i=0; $retrievals = array();
foreach($types as $key => $type) {
+ $retrievals[$i] = array();
$map = $ids = array();
$field = (is_numeric($key)) ? $type : $key;//use an alias?
+ $addToStack = true;
+ if (strpos($field,'*')!==false) { $field = str_replace('*',implode('.',$oldFields),$field); $addToStack = true; }
+ if (strpos($field,'&')!==false) { $field = str_replace('&',implode('.',$oldFields),$field); $addToStack = false; }
$filteredBeans = $beans;
while($p = strpos($field,'.')) { //filtering: find the right beans in the path
$nesting = substr($field,0,$p);
@@ -912,13 +931,12 @@ public function preload($beans, $types) {
$field = substr($field,$p+1);
}
if (strpos($type,'.')) $type = $field;
+ if ($addToStack) $oldFields[]= $field;
foreach($filteredBeans as $bean) { //gather ids to load the desired bean collections
if (strpos($field,'own')===0) { //based on bean->id for ownlist
- $id = $bean->id;
- $ids[$id] = $id;
+ $id = $bean->id; $ids[$id] = $id;
} elseif($id = $bean->{$field.'_id'}){ //based on bean_id for parent
- $ids[$id] = $id;
- if (!isset($map[$id])) $map[$id] = array();
+ $ids[$id] = $id; if (!isset($map[$id])) $map[$id] = array();
$map[$id][] = $bean;
}
}
@@ -931,14 +949,26 @@ public function preload($beans, $types) {
if ($child->$link==$bean->id) $list[$child->id] = $child;
}
$bean->setProperty($field,$list);
+ $retrievals[$i][] = $list;
}
} else { //preload for parent objects using batch()
foreach($this->batch($type,$ids) as $parent) {
foreach($map[$parent->id] as $childBean) {
$childBean->setProperty($field,$parent);
+ $retrievals[$i][] = $parent;
}
}
- }
+ }
+ $i++;
+ }
+ if ($closure) {
+ $key = 0; foreach($beans as $bean) {
+ $params = array();
+ foreach($retrievals as $r) $params[] = (isset($r[$key])) ? $r[$key] : null;
+ array_unshift($params,$bean);
+ call_user_func_array($closure,$params);
+ $key ++;
+ }
}
}
}
@@ -22,7 +22,7 @@ class RedUNIT_Base_Preloading extends RedUNIT_Base {
* @return void
*/
public function run() {
-
+
//test without preload
R::nuke();
$books = R::dispense('book',3);
@@ -239,6 +239,108 @@ public function run() {
asrt($text->page,null);
+
+ //test with closure
+ R::nuke();
+ $books = R::dispense('book',3);
+ $i=0;
+ foreach($books as $book) {
+ $i++;
+ $book->name = $i;
+ $book->ownPage[] = R::dispense('page')->setAttr('name',$i);
+ $book->author = R::dispense('author')->setAttr('name',$i);
+ $book->coauthor = R::dispense('author')->setArr('name',$i);
+ }
+ R::storeAll($books);
+ $books = R::find('book');
+ $hasNuked = false;
+ R::preload($books,'author',function($book,$author){
+ global $hasNuked;
+ if (!$hasNuked) { R::nuke(); $hasNuked = true; }
+ asrt($book->getMeta('type'),'book');
+ asrt($author->getMeta('type'),'author');
+ });
+
+ //test with closure and abbrevations
+ R::nuke();
+ $authors = R::dispense('author',2);
+ foreach($authors as $author) {
+ $author->ownBook = R::dispense('book',2);
+ foreach($author->ownBook as $book) {
+ $book->ownPage = R::dispense('page',2);
+ foreach($book->ownPage as $page) $page->ownText = R::dispense('text',2);
+ }
+ }
+ R::storeAll($authors);
+ $texts = R::find('text');
+ $hasNuked = false;
+ R::preload($texts,'page,*.book,*.author',function($text,$page,$book,$author){
+ global $hasNuked;
+ if (!$hasNuked) { R::nuke(); $hasNuked = true; }
+ asrt($text->getMeta('type'),'text');
+ asrt($page->getMeta('type'),'page');
+ asrt($book->getMeta('type'),'book');
+ asrt($author->getMeta('type'),'author');
+ });
+
+ //test with closure and abbrevations and same-level abbr
+ R::nuke();
+ $authors = R::dispense('author',2);
+ foreach($authors as $author) {
+ $author->ownBook = R::dispense('book',2);
+ foreach($author->ownBook as $book) {
+ $book->ownPage = R::dispense('page',2);
+ foreach($book->ownPage as $page) $page->ownText = R::dispense('text',2);
+ }
+ }
+ foreach($authors as $author) {
+ foreach($author->ownBook as $book) {
+ $book->shelf = R::dispense('shelf')->setAttr('name','abc');
+ }
+ }
+ R::storeAll($authors);
+ $texts = R::find('text');
+ $hasNuked = false;
+ R::preload($texts,'page,*.book,&.author,*.shelf',function($text,$page,$book,$author,$shelf){
+ global $hasNuked;
+ if (!$hasNuked) { R::nuke(); $hasNuked = true; }
+ asrt($text->getMeta('type'),'text');
+ asrt($page->getMeta('type'),'page');
+ asrt(($page->id>0),true);
+ asrt($book->getMeta('type'),'book');
+ asrt(($book->id>0),true);
+ asrt($author->getMeta('type'),'author');
+ asrt($shelf->getMeta('type'),'shelf');
+ });
+
+ //test with closure, abbreviation and own-list
+ R::nuke();
+ $authors = R::dispense('author',2);
+ foreach($authors as $author) {
+ $author->ownBook = R::dispense('book',2);
+ foreach($author->ownBook as $book) {
+ $book->ownPage = R::dispense('page',2);
+ foreach($book->ownPage as $page) $page->ownText = R::dispense('text',2);
+ }
+ }
+ R::storeAll($authors);
+ $pages = R::find('page');
+ $hasNuked = false;
+ R::preload($pages,array('book','*.author','ownText'=>'text'),function($page,$book,$author,$texts){
+ global $hasNuked;
+ if (!$hasNuked) { R::nuke(); $hasNuked = true; }
+ asrt($page->getMeta('type'),'page');
+ asrt(($page->id>0),true);
+ asrt($book->getMeta('type'),'book');
+ asrt(($book->id>0),true);
+ asrt($author->getMeta('type'),'author');
+ asrt(($author->id>0),true);
+ asrt(is_array($texts),true);
+ asrt(count($texts),2);
+ $first = reset($texts);
+ asrt($first->getMeta('type'),'text');
+ });
+
}
}

0 comments on commit 060c195

Please sign in to comment.