34
loading...
This website collects cookies to deliver better user experience
pluck
is used to grab a single field quickly; like a list of email addresses.select(...)
and then run additional operations on it. SELECT CONCAT(`fieldA`, `fieldB`) as `fieldName`
FROM ...
type
and slug
glued by a hyphen, such that our results look like:Array
(
[0] => 1-acting
[1] => 1-animation
[2] => 1-cinematography
[3] => 2-concept
[4] => 2-directing
[5] => 2-editing
[6] => 3-music
[7] => 3-none
[8] => 3-production-design
)
/**
* Selects multiple columns and concatenates them using a specified glue
*
* @param array $fields
* @param string $glue
* @return BaseBuilder
*/
public function pluckMultiple(array $fields, string $glue = '-'): \Illuminate\Support\Collection
{
return $this->select($fields)
->get()
->map(function($model, $key) use ($fields, $glue) {
return implode($glue, array_values(array_intersect_key($model->toArray(), array_flip($fields))));
});
}
$result = MyModel::pluckMultiple(['type', 'slug'], '-')->toArray();
// produces the above output
public function pluckMultiple(
// Accept an array of fields, e.g. ['id', 'name']
array $fields,
// Define the glue for implosion, could be empty ''
string $glue = '-'
// Return Laravel collection for chaining more methods
): \Illuminate\Support\Collection
{
// Run basic SELECT `fieldA`, `fieldB`
// ❗️ Might want to modify this to accept all fields
// so you can leverage cached queries.
// ❗️ It's also possible to write the raw query we
// talked about before here
return $this->select($fields)
// Receive all results (❗️ This could get expensive)
->get()
// Run operations on each row, pass in $fields + $glue
// Our code above combines these steps into a single line
->map(function($model, $key) use ($fields, $glue) {
// Get our model as basic array
$arrayOfData = $model->toArray();
// Flip our fields values into their keys position
// e.g. ['id', 'slug'] becomes
// ['id' => 0, 'slug' => 1]
$reversedFields = array_flip($fields);
// Find intersection of keys e.g. 'id' and 'slug'
$intersection = array_intersect_key($arrayOfData, $reversedFields);
// Get only values from resulting intersection
// e.g. [1, 'my-slug']
$values = array_values($intersection);
// Combine values using glue
// e.g. '1-my-slug'
$gluedResult = implode($glue, $values);
// Use this result as our collection item
return $gluedResult;
});
}
select(...)
query to only the fields we want, we are now creating additional read queries for what might be a commonly used table.SELECT *
, then it'd likely be valuable to use the results from the previous execution here rather than creating a new transaction.get()
+ map()
allows for maximum flexibility but it could be slow if you are dealing with large datasets. If you're intending to perform this method on a large dataset or if you think it'll be run frequently with dynamic data, it may be wise to put this logic directly into the SQL query itself rather than iterating through it.$fields = ['id', 'slug'];
$sql = sprintf("
SELECT CONCAT(`%s`) as `concatenatedResult`
FROM `table`
LIMIT 9999
", implode('`, `', $fields));
// Prints:
// SELECT CONCAT(`id`, `slug`) as `concatenatedResult`
// FROM `table`
// LIMIT 9999
pluckMethod
in a Laravel environment.