diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index 2011c54374f7..201fa62f4a07 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -334,6 +334,33 @@ public function selectOne($query, $bindings = [], $useReadPdo = true) return array_shift($records); } + /** + * Run a select statement and return the first column of the first row. + * + * @param string $query + * @param array $bindings + * @param bool $useReadPdo + * @return mixed + * + * @throws MultipleColumnsSelectedException + */ + public function scalar($query, $bindings = [], $useReadPdo = true) + { + $record = $this->selectOne($query, $bindings, $useReadPdo); + + if (is_null($record)) { + return null; + } + + $record = (array) $record; + + if (count($record) > 1) { + throw new MultipleColumnsSelectedException; + } + + return reset($record); + } + /** * Run a select statement against the database. * diff --git a/src/Illuminate/Database/MultipleColumnsSelectedException.php b/src/Illuminate/Database/MultipleColumnsSelectedException.php new file mode 100644 index 000000000000..07c86fdf4658 --- /dev/null +++ b/src/Illuminate/Database/MultipleColumnsSelectedException.php @@ -0,0 +1,10 @@ +assertSame('foo', $connection->selectOne('foo', ['bar' => 'baz'])); } + public function testScalarCallsSelectOneAndReturnsSingleResult() + { + $connection = $this->getMockConnection(['selectOne']); + $connection->expects($this->once())->method('selectOne')->with('select count(*) from tbl')->willReturn((object) ['count(*)' => 5]); + $this->assertSame(5, $connection->scalar('select count(*) from tbl')); + } + + public function testScalarThrowsExceptionIfMultipleColumnsAreSelected() + { + $connection = $this->getMockConnection(['selectOne']); + $connection->expects($this->once())->method('selectOne')->with('select a, b from tbl')->willReturn((object) ['a' => 'a', 'b' => 'b']); + $this->expectException(MultipleColumnsSelectedException::class); + $connection->scalar('select a, b from tbl'); + } + + public function testScalarReturnsNullIfUnderlyingSelectReturnsNoRows() + { + $connection = $this->getMockConnection(['selectOne']); + $connection->expects($this->once())->method('selectOne')->with('select foo from tbl where 0=1')->willReturn(null); + $this->assertNull($connection->scalar('select foo from tbl where 0=1')); + } + public function testSelectProperlyCallsPDO() { $pdo = $this->getMockBuilder(DatabaseConnectionTestMockPDO::class)->onlyMethods(['prepare'])->getMock();