From 939cb81d85a72124d0f58ee49d4ca0e35aae9127 Mon Sep 17 00:00:00 2001 From: Dennis Birkholz Date: Fri, 4 Dec 2015 16:24:22 +0100 Subject: [PATCH] Make it possible to iterate over results with foreach($result AS $rowNo => $rowContent) ... --- src/Response/Response.php | 2 +- src/Response/Result.php | 10 ++- src/Response/ResultIterator.php | 107 ++++++++++++++++++++++++++++++++ src/Response/StreamReader.php | 9 +++ 4 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 src/Response/ResultIterator.php diff --git a/src/Response/Response.php b/src/Response/Response.php index 93a2d50..e399c0c 100644 --- a/src/Response/Response.php +++ b/src/Response/Response.php @@ -9,7 +9,7 @@ class Response implements Frame{ protected $_header; /** - * @var + * @var StreamReader */ protected $_stream; diff --git a/src/Response/Result.php b/src/Response/Result.php index c70d6a0..87a137d 100644 --- a/src/Response/Result.php +++ b/src/Response/Result.php @@ -3,7 +3,7 @@ use Cassandra\Protocol\Frame; use Cassandra\Type; -class Result extends Response { +class Result extends Response implements \IteratorAggregate { const VOID = 0x0001; const ROWS = 0x0002; const SET_KEYSPACE = 0x0003; @@ -311,4 +311,12 @@ public function fetchOne(){ return null; } + + /** + * @return + */ + public function getIterator() { + return new ResultIterator($this->_stream, $this->getMetadata(), $this->_rowClass); + } + } diff --git a/src/Response/ResultIterator.php b/src/Response/ResultIterator.php new file mode 100644 index 0000000..5be2367 --- /dev/null +++ b/src/Response/ResultIterator.php @@ -0,0 +1,107 @@ + + */ +class ResultIterator implements \Iterator { + /** + * Stream containing the raw result data + * + * @var StreamReader + */ + private $stream; + + /** + * Offset to start reading data in this stream + * + * @var int + */ + private $offset; + + /** + * Metadata generated by the creating Result + * + * @var array + */ + private $metadata; + + /** + * Class to use for each row of data + * + * @var string + */ + private $rowClass; + + /** + * Number of available rows in the resultset + * + * @var int + */ + private $count; + + /** + * Current row + * + * @var int + */ + private $row = 0; + + + public function __construct(StreamReader $stream, array $metadata, $rowClass) { + $this->stream = clone $stream; + $this->metadata = $metadata; + $this->count = $this->stream->readInt(); + $this->offset = $this->stream->pos(); + $this->rewind(); + } + + public function current() { + $data = []; + + foreach ($this->metadata['columns'] as $column) { + $data[$column['name']] = $this->stream->readValue($column['type']); + } + + $rowClass = $this->rowClass; + return ($rowClass === null ? $data : new $rowClass($data)); + } + + /** + * The current position in this result set + * + * @return int + */ + public function key() { + return $this->row; + } + + /** + * Move forward to next element + * + * @return void + */ + public function next() { + $this->row++; + } + + /** + * Reset the result set + * + * @return void + */ + public function rewind() { + $this->row = 0; + $this->stream->offset($this->offset); + } + + /** + * Checks if current position is valid + * + * @return boolean + */ + public function valid() { + return (($this->row >= 0) && ($this->row < $this->count)); + } +} diff --git a/src/Response/StreamReader.php b/src/Response/StreamReader.php index 51f4dca..e93b39d 100644 --- a/src/Response/StreamReader.php +++ b/src/Response/StreamReader.php @@ -40,6 +40,15 @@ public function offset($offset){ public function reset(){ $this->offset = 0; } + + /** + * Get the current position of this stream + * + * @return int + */ + public function pos() { + return $this->offset; + } /** * Read single character.