Skip to content

Commit

Permalink
Add support for JsonSerializable.
Browse files Browse the repository at this point in the history
Fix issues with deserializing ResultSets, where a `false` would be
appended to the stored results.
  • Loading branch information
markstory committed Aug 5, 2013
1 parent 66e9970 commit cd1278d
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 16 deletions.
33 changes: 23 additions & 10 deletions lib/Cake/ORM/ResultSet.php
Expand Up @@ -18,6 +18,7 @@

use Cake\Database\Type;
use \Iterator;
use \JsonSerializable;
use \Serializable;

/**
Expand All @@ -27,7 +28,7 @@
* queries required for eager loading external associations.
*
*/
class ResultSet implements Iterator, Serializable {
class ResultSet implements Iterator, Serializable, JsonSerializable {

/**
* Original query from where results where generated
Expand Down Expand Up @@ -200,20 +201,21 @@ protected function _calculateAssociationMap() {
* @return void
*/
protected function _fetchResult() {
$advance = ($this->_lastIndex < $this->_index);
if (!$advance) {
return;
}
if (isset($this->_results[$this->_index])) {
$this->_current = $this->_results[$this->_index];
$this->_lastIndex = $this->_index;
return;
}
if (!$this->_statement) {
$this->_current = false;
return;
}
$row = $this->_statement->fetch('assoc');
if ($row !== false) {
$row = $this->_groupResult($row);
$this->_results[] = $row;
}
$this->_current = $row;
$this->_results[] = $row;
$this->_lastIndex = $this->_index;
}

Expand Down Expand Up @@ -290,26 +292,37 @@ protected function _castValues($table, $values) {
/**
* Serialize a resultset.
*
* Part of Serializable Interface
* Part of Serializable interface.
*
* @return string Serialized object
*/
public function serialize() {
iterator_to_array($this);
$this->toArray();
return serialize($this->_results);
}

/**
* Unserialize a resultset.
*
* Part of Serializable Interface
* Part of Serializable interface.
*
* @param string Serialized object
* @return ResultSet The hydrated result set.
*/
public function unserialize($serialized) {
$this->_results = unserialize($serialized);
return $this;
}

/**
* Convert a result set into JSON.
*
* Part of JsonSerializable interface.
*
* @return array The data to convert to JSON
*/
public function jsonSerialize() {
$this->toArray();
return $this->_results;
}

}
26 changes: 20 additions & 6 deletions lib/Cake/Test/TestCase/ORM/ResultSetTest.php
Expand Up @@ -34,6 +34,12 @@ public function setUp() {
parent::setUp();
$this->connection = ConnectionManager::getDataSource('test');
$this->table = new Table(['table' => 'articles', 'connection' => $this->connection]);

$this->fixtureData = [
['id' => 1, 'author_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y'],
['id' => 2, 'author_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y'],
['id' => 3, 'author_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y']
];
}

/**
Expand Down Expand Up @@ -83,15 +89,23 @@ public function testIteratorAfterSerialization() {
$query = $this->table->find('all');
$results = unserialize(serialize($query->execute()));

$expected = [
['id' => 1, 'author_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y'],
['id' => 2, 'author_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y'],
['id' => 3, 'author_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y']
];
// Use a loop to test Iterator implementation
foreach ($results as $i => $row) {
$this->assertEquals($expected[$i], $row, "Row $i does not match");
$this->assertEquals($this->fixtureData[$i], $row, "Row $i does not match");
}
}

/**
* Test converting resultsets into json
*
* @return void
*/
public function testJsonSerialize() {
$query = $this->table->find('all');
$results = $query->execute();

$expected = json_encode($this->fixtureData);
$this->assertEquals(json_encode($results), $expected);
}

}

0 comments on commit cd1278d

Please sign in to comment.