I'm trying to use Laravel collections for a simple case. I'm building a collection of furniture items and I would like to amend the item lines with additional information afterwards :
$collection = collect([
['name' => 'Desk', 'color' => 'Black'],
['name' => 'Chair', 'color' => 'Black'],
['name' => 'Bookcase', 'color' => 'Red'],
]);
I would like to add a 'stock_value' field for some items, based on the item key 'name' (for instance). In the end, I would like the collection to become something like :
['name' => 'Desk', 'color' => 'Black', 'stock_value' => 4],
['name' => 'Chair', 'color' => 'Black'],
['name' => 'Bookcase', 'color' => 'Red', 'stock_value' => 9]
I don't know how to achieve that. Any help would be greatly appreciated.
$stockValue = 9;
return $collection->transform(function ($array) use ($stockValue) {
if ($array['name'] === 'Desk') {
$array['stock_value'] = $stockValue;
}
return $array;
});
You may use transform to modify your collection.
Related
I have the following collection
$collection = collect([
['id' => 1, 'name' => 'Design'],
['id' => 2, 'name' => 'Art'],
['id' => 3, 'name' => 'Comms'],
['id' => 2, 'name' => 'Art'],
['id' => 3, 'name' => 'Comms'],
['id' => 3, 'name' => 'Comms'],
]);
I want only unique items in the collection and the collection should be sorted by number of duplicates. So an item which has most number of duplicates must appear on top as follows
$collection = collect([
['id' => 3, 'name' => 'Comms'],
['id' => 2, 'name' => 'Art'],
['id' => 1, 'name' => 'Design'],
]);
I can remove duplicates using unique method but cannot find a want to sort them.
You can do it with mapWithKeys()
https://laravel.com/docs/8.x/collections#method-mapwithkeys
$collection = $collection->groupBy('id')->mapWithKeys(function (Collection $row) {
return [$row->count() => $row->first()];
})->sortKeysDesc();
i was finding method for fetching item in collection by specific key and value, and i have found one which is where(),
But i also want to delete that item after fetching it from original collection, but i couldn't find any method which can do both.
i have seen pull() method but it fetches by key and removes that column from collection but i want to remove particular item only.
I have looked in collection doc, but couldn't find any native method so i am using 2 method to achieve that need, the code is as below:
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Door', 'price' => 100],
]);
$filtered_items = $collection->where('price', 100);
$filtered_collection = $collection->whereNotIn('price', [100]);
i am thinking that above 2 method will be little overhead if i can accomplish it in one method, so i am looking for other solutions guys, thanks beforehand your answers.
You need this one https://laravel.com/docs/5.5/collections#method-partition
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Door', 'price' => 100],
]);
$filtered_items = $collection->where('price', 100);
list($neededCollection, $filteredCollection) = $collection->partition(function ($i) {
return $i['price'] == 100;
});
dd($neededCollection, $filteredCollection);
result like this
I saw the example of laravel, but i dont understand how do it work.
for this example:
$collection = collect([
[
'name' => 'John',
'department' => 'Sales',
'email' => 'john#example.com'
],
[
'name' => 'Jane',
'department' => 'Marketing',
'email' => 'jane#example.com'
]
]);
$keyed = $collection->mapWithKeys(function ($item) {
return [$item['email'] => $item['name']];
});
$keyed->all();
someone can explain detail of it?
$collection = collect([
[
'name' => 'John',
'department' => 'Sales',
'email' => 'john#example.com'
],
[
'name' => 'Jane',
'department' => 'Marketing',
'email' => 'jane#example.com'
]
]);
$keyed = $collection->mapWithKeys(function ($item) {
//this line takes one array of collection object in item array and make a key of its email and store name on that email key
return [$item['email'] => $item['name']];
});
$keyed->all();
I have an array storing 3 merged collections:
public function answer() {
$interview = Interview::find(1);
$videoQuestions = $interview->VideoQuestions()->get();
foreach ($videoQuestions as $vq) {
$vq->type = 'video';
}
$textQuestions = $interview->TextQuestions()->get();
foreach ($textQuestions as $tq) {
$tq->type = 'text';
}
$uploadQuestions = $interview->UploadQuestions()->get();
foreach ($uploadQuestions as $uq) {
$uq->type = 'upload';
}
$questions = collect($videoQuestions);
$questions = $questions->merge($textQuestions);
$questions = $questions->merge($uploadQuestions);
$questions->sortBy('order_position');
dd($questions);
}
The ->sortBy is not working as I assume it doesn't work on an array of collections.
This is what I have:
But I really just want it to be a merged collection not an array inside the collection.
Each VideoQuestion or TextQuestion has an order_position field that I would like to sort by.
Any help is appreciated!
First thing collection is a class containing an array of elements with special methods to filter sort, docs:
The Illuminate\Support\Collection class provides a fluent, convenient
wrapper for working with arrays of data.
The sortBy method returns a sorted collection (it does not apply to the item it has):
$collection = collect([
['name' => 'Desk', 'price' => 200],
['name' => 'Chair', 'price' => 100],
['name' => 'Bookcase', 'price' => 150],
]);
$sorted = $collection->sortBy('price');
$sorted->values()->all();
/*
[
['name' => 'Chair', 'price' => 100],
['name' => 'Bookcase', 'price' => 150],
['name' => 'Desk', 'price' => 200],
]
*/
So you should have something like:
$questions = $questions->sortBy('order_position');
dd($questions);
This could be an alternative:
$interview = Interview::find(1)->with(['VideoQuestions',
'TextQuestions',
'UploadQuestions',
'Questions' => function($query){
$query->orderBy('order_position', 'asc');
}])->get();
Define the relationships and make a table Questions that holds an order_position that you can sort on instead of each table.
I'm trying to make a collection from some arrays of data:
$myCollection = collect(
['product_id' => 1, 'price' => 200, 'discount' => '50'],
['product_id' => 2, 'price' => 400, 'discount' => '50']
);
When I loop out I would like to do:
foreach ($myCollection as $product) {
echo $product->price;
echo $product->discount;
}
But the underlying elements appear to still be in an arrays format, how can I achieve the above output?
If you want the inner arrays to be a collection, then you can do so as follows:
$myCollection = collect([
['product_id' => 1, 'price' => 200, 'discount' => '50'],
['product_id' => 2, 'price' => 400, 'discount' => '50']
])->map(function($row) {
return collect($row);
});
If you want the inner arrays to be objects, then you can do as follows:
$myCollection = collect([
['product_id' => 1, 'price' => 200, 'discount' => '50'],
['product_id' => 2, 'price' => 400, 'discount' => '50']
])->map(function($row) {
return (object) $row;
});
You can also iterate over each of the results...
$myCollection = collect([
['product_id' => 1, 'price' => 200, 'discount' => '50'],
['product_id' => 2, 'price' => 400, 'discount' => '50']
])->map(function($row) {
return (object) $row;
})->each(function($row) {
echo sprintf('ProductId: %d, Price: %d, Discount: %s'.PHP_EOL, $row->product_id, $row->price, $row->discount);
});
Output:
ProductId: 1, Price: 200, Discount: 50
ProductId: 2, Price: 400, Discount: 50
Simple as you are getting a collection of an associative arrays because you are collecting arrays elements, so the collection helper doesn't want to modify it in case you need it as array.
Knowing this, if you want to collect objects you should pass an element of object type.
You can cast object data type into the array, like this:
$myCollection = collect( (object) array(
(object) ['product_id' => 1, 'price' => 200, 'discount' => '50'],
(object) ['product_id' => 2, 'price' => 400, 'discount' => '50'])
);
Then you have a collection of objects !
Function collect() takes array of elements. You can fix your code also by enclosing all the elements into [] and then converting Collection elements to objects instead of leaving them to be arrays
$myCollection = collect([
(object)(['product_id' => 1, 'price' => 200, 'discount' => '50']),
(object)(['product_id' => 2, 'price' => 400, 'discount' => '50'])
]
);
foreach ($myCollection as $product) {
echo $product->price;
echo $product->discount;
}
There's a syntax error in your collection definition:
$myCollection = collect([
['product_id' => 1, 'price' => 200, 'discount' => '50'],
['product_id' => 2, 'price' => 400, 'discount' => '50']
]);
Also, since you're using a Collection, you no longer need to use a foreach loop:
$myCollection->each(function ($item) {
echo $item['price'];
})