diff --git a/src/Illuminate/Database/Query/Builder.php b/src/Illuminate/Database/Query/Builder.php index 36eea18842c3..39215ee28301 100755 --- a/src/Illuminate/Database/Query/Builder.php +++ b/src/Illuminate/Database/Query/Builder.php @@ -1830,17 +1830,11 @@ public function value($column) */ public function get($columns = ['*']) { - $original = $this->columns; - - if (is_null($original)) { - $this->columns = $columns; - } - - $results = $this->processor->processSelect($this, $this->runSelect()); - - $this->columns = $original; - - return collect($results); + return collect( + $this->onceWithColumns($columns, function () { + return $this->processor->processSelect($this, $this->runSelect()); + }) + ); } /** @@ -2036,15 +2030,52 @@ protected function enforceOrderBy() */ public function pluck($column, $key = null) { - $results = $this->get(is_null($key) ? [$column] : [$column, $key]); + $queryResult = $this->onceWithColumns( + is_null($key) ? [$column] : [$column, $key], + function () { + return $this->processor->processSelect($this, $this->runSelect()); + } + ); + + if (empty($queryResult)) { + return collect(); + } // If the columns are qualified with a table or have an alias, we cannot use // those directly in the "pluck" operations since the results from the DB // are only keyed by the column itself. We'll strip the table out here. - return $results->pluck( - $this->stripTableForPluck($column), - $this->stripTableForPluck($key) - ); + $column = $this->stripTableForPluck($column); + $key = $this->stripTableForPluck($key); + + if (is_array($queryResult[0])) { + return $this->pluckFromArrayColumn($queryResult, $column, $key); + } else { + return $this->pluckFromObjectColumn($queryResult, $column, $key); + } + } + + /** + * Execute the given callback while selecting the given columns. + * + * After running the callback, the columns are reset to the original value. + * + * @param array $columns + * @param callable $callback + * @return mixed + */ + protected function onceWithColumns($columns, $callback) + { + $original = $this->columns; + + if (is_null($original)) { + $this->columns = $columns; + } + + $result = $callback(); + + $this->columns = $original; + + return $result; } /** @@ -2058,6 +2089,56 @@ protected function stripTableForPluck($column) return is_null($column) ? $column : last(preg_split('~\.| ~', $column)); } + /** + * Retrieve column values from rows represented as objects. + * + * @param array $queryResult + * @param string $column + * @param string $key + * @return \Illuminate\Support\Collection + */ + protected function pluckFromObjectColumn($queryResult, $column, $key) + { + $results = []; + + if (is_null($key)) { + foreach ($queryResult as $row) { + $results[] = $row->$column; + } + } else { + foreach ($queryResult as $row) { + $results[$row->$key] = $row->$column; + } + } + + return collect($results); + } + + /** + * Retrieve column values from rows represented as arrays. + * + * @param array $queryResult + * @param string $column + * @param string $key + * @return \Illuminate\Support\Collection + */ + protected function pluckFromArrayColumn($queryResult, $column, $key) + { + $results = []; + + if (is_null($key)) { + foreach ($queryResult as $row) { + $results[] = $row[$column]; + } + } else { + foreach ($queryResult as $row) { + $results[$row[$key]] = $row[$column]; + } + } + + return collect($results); + } + /** * Concatenate values of a given column as a string. * diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php index 5f524a88c60c..81033544c756 100755 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ b/tests/Database/DatabaseQueryBuilderTest.php @@ -1315,7 +1315,7 @@ public function testFirstMethodReturnsFirstResult() $this->assertEquals(['foo' => 'bar'], $results); } - public function testListMethodsGetsArrayOfColumnValues() + public function testPluckMethodGetsCollectionOfColumnValues() { $builder = $this->getBuilder(); $builder->getConnection()->shouldReceive('select')->once()->andReturn([['foo' => 'bar'], ['foo' => 'baz']]);