Skip to content

Commit

Permalink
Adding Collection::compile as a way to optimize operations with a single
Browse files Browse the repository at this point in the history
collection
  • Loading branch information
lorenzo committed Dec 28, 2013
1 parent 53a2046 commit c7b7f53
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
36 changes: 36 additions & 0 deletions Cake/Collection/CollectionTrait.php
Expand Up @@ -649,4 +649,40 @@ public function jsonSerialize() {
return $this->toArray();
}

/**
* Iterates once all elements in this collection and executes all stacked
* operations of them, finally it returns a new collection with the result.
* This is useful for converting non-rewindable internal iterators into
* a collection that can be rewound and used multiple times.
*
* A common use case is to re-use the same variable for calculating different
* data. In those cases it may be helpful and more performant to first compile
* a collection and then apply more operations to it.
*
* ### Example:
*
* {{{
* $collection->map($mapper)->sortBy('age')->extract('name');
* $compiled = $collection->compile();
* $isJohnHere = $compiled->some($johnMatcher);
* $allButJohn = $compiled->filter($johnMatcher);
* }}}
*
* In the above example, had not the collection compiled before, the iterations
* for `map`, `sortBy` and `extract` would've been executed twice: once for
* getting `$isJohnHere` and once for `$allButJohn`
*
* You can think of this method as a way to create save points for complex
* calculations in a collection.
*
* @param boolean $preserveKeys whether to use the keys returned by this
* collection as the array keys. Keep in mind that it is valid for iterators
* to return the same key for different elements, setting this value to false
* can help getting all items if keys are not important in the result.
* @return \Cake\Collection\Collection
*/
public function compile($preserveKeys = true) {
return new Collection($this->toArray($preserveKeys));
}

}
27 changes: 27 additions & 0 deletions Cake/Test/TestCase/Collection/CollectionTest.php
Expand Up @@ -604,4 +604,31 @@ public function testAppend() {
$this->assertEquals(['a' => 4, 'b' => 2, 'c' => 3], $combined->toArray());
}

/**
* Tests that by calling compile internal iteration operations are not done
* more than once
*
* @return void
*/
public function testCompile() {
$items = ['a' => 1, 'b' => 2, 'c' => 3];
$collection = new Collection($items);
$callable = $this->getMock('stdClass', ['__invoke']);
$callable->expects($this->at(0))
->method('__invoke')
->with(1, 'a')
->will($this->returnValue(4));
$callable->expects($this->at(1))
->method('__invoke')
->with(2, 'b')
->will($this->returnValue(5));
$callable->expects($this->at(2))
->method('__invoke')
->with(3, 'c')
->will($this->returnValue(6));
$compiled = $collection->map($callable)->compile();
$this->assertEquals(['a' => 4, 'b' => 5, 'c' => 6], $compiled->toArray());
$this->assertEquals(['a' => 4, 'b' => 5, 'c' => 6], $compiled->toArray());
}

}

0 comments on commit c7b7f53

Please sign in to comment.