diff --git a/src/Result/ResultSet.php b/src/Result/ResultSet.php index b1f2370..216adf3 100644 --- a/src/Result/ResultSet.php +++ b/src/Result/ResultSet.php @@ -85,6 +85,32 @@ public function asArray():array { ); } + /** @return array */ + public function getFieldList():array { + $fieldCount = $this->statement->columnCount(); + $fieldList = []; + for($i = 0; $i < $fieldCount; $i++) { + $meta = $this->statement->getColumnMeta($i); + $name = $meta["name"] ?? null; + if(is_string($name)) { + $fieldList[] = $name; + } + } + + if(!empty($fieldList)) { + return $fieldList; + } + +// Some drivers may not have the column meta - fetch the first row and reset. + $currentIteratorIndex = $this->iteratorIndex; + $this->rewind(); + $row = $this->fetch(); + $fieldList = $row?->getFieldList() ?? []; + $this->rewind(); + $this->iteratorIndex = $currentIteratorIndex; + return $fieldList; + } + public function rewind():void { $this->statement->execute(); $this->currentRow = null; diff --git a/src/Result/Row.php b/src/Result/Row.php index 4316b25..e852c84 100644 --- a/src/Result/Row.php +++ b/src/Result/Row.php @@ -67,6 +67,11 @@ public function asArray():array { return $this->data; } + /** @return array */ + public function getFieldList():array { + return array_keys($this->data); + } + public function contains(string $name):bool { return $this->__isset($name); } diff --git a/test/phpunit/Result/ResultSetTest.php b/test/phpunit/Result/ResultSetTest.php index d060954..97bb996 100644 --- a/test/phpunit/Result/ResultSetTest.php +++ b/test/phpunit/Result/ResultSetTest.php @@ -88,6 +88,44 @@ public function testCountTwice() { self::assertCount($count, $resultSet); } + public function testGetFieldList() { + $resultSet = new ResultSet($this->getStatementMock()); + self::assertSame( + ["id", "name", "timestamp", "date"], + $resultSet->getFieldList() + ); + } + + public function testGetFieldListFallbackToFirstRow() { + $resultSet = new ResultSet($this->getStatementMock(false)); + self::assertSame( + ["id", "name", "timestamp", "date"], + $resultSet->getFieldList() + ); + } + + public function testGetFieldListNoRows() { + $statement = $this->createMock(PDOStatement::class); + $statement->method("fetch")->willReturn(null); + $statement->method("execute")->willReturn(true); + $statement->method("columnCount")->willReturn(0); + $resultSet = new ResultSet($statement); + + self::assertSame([], $resultSet->getFieldList()); + } + + public function testGetFieldListMidIteration() { + $resultSet = new ResultSet($this->getStatementMock()); + $resultSet->rewind(); + $resultSet->next(); + + self::assertSame( + ["id", "name", "timestamp", "date"], + $resultSet->getFieldList() + ); + self::assertEquals(2, $resultSet->current()->id); + } + public function testAccessByRowIndex() { $resultSet = new ResultSet($this->getStatementMock()); @@ -137,12 +175,25 @@ public function testAsDateTime() { self::assertEquals("1988-04-05 17:24", $row->getDateTime("timestamp")->format("Y-m-d H:i")); } - private function getStatementMock():PDOStatement { + private function getStatementMock(bool $withMetadata = true):PDOStatement { $statement = $this->createMock(PDOStatement::class); $statement->method("fetch") ->will(self::returnCallback([$this, "getNextFakeData"])); $statement->method("execute") ->willReturnCallback([$this, "rewindFakeData"]); + if($withMetadata) { + $statement->method("columnCount") + ->willReturn(count(self::FAKE_DATA[0])); + $statement->method("getColumnMeta") + ->willReturnCallback(function(int $index):array { + $name = array_keys(self::FAKE_DATA[0])[$index] ?? null; + return ["name" => $name]; + }); + } + else { + $statement->method("columnCount") + ->willReturn(0); + } return $statement; } diff --git a/test/phpunit/Result/RowTest.php b/test/phpunit/Result/RowTest.php index 4f4865d..8d861a7 100644 --- a/test/phpunit/Result/RowTest.php +++ b/test/phpunit/Result/RowTest.php @@ -56,6 +56,19 @@ public function testContains() { self::assertFalse($row->contains("col2")); } + public function testGetFieldList() { + $row = new Row([ + "id" => 123, + "name" => "Example", + "enabled" => 1, + ]); + + self::assertSame( + ["id", "name", "enabled"], + $row->getFieldList() + ); + } + /** @dataProvider data_getTestRow */ public function testIteration(array $data) { $row = new Row($data);