How to Get specific keys of multi-dimensional array with Arr::only() - laravel

Can I use Arr::only() to get specific keys in multidimensional array ?
Dot notation doesn't work in this case:
use Illuminate\Support\Arr;
$array = ['name' => 'Desk', 'model.small.price' => 100, 'orders' => 10];
$slice = Arr::only($array, ['name', 'model.small.price']);
// ['name' => 'Desk', 'model.small.price' => 100]

Related

add data to a Laravel collection

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.

Method for getting items from collection with specific key, value pair and also remove it from original collection in laravel

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

Sorting array of collections

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.

Creating a collection from a multidimensional array?

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'];
})

Session::instance() and push array data to session array

for example i have Session::instance()->get('orders') which is an array of some arrays:
$first = array('id' = 1, 'name' => 'first', 'price' => 100);
$second = array('id' => 2, 'name' => 'second', 'price' => 200);
$_SESSION['orders'] = array($first, $second);
but if i use this
Session::instance()->set('orders', array(array('id' => 3, 'name' => 'third', 'price' => 300)));
this will erase first orders (id 1, id 2).
so how can i ADD but not ERASE data arrays to session array named 'orders'? array_push or something else?
Edit, didn't see your comment, it's perfect.
Self explanatory.
$session = Session::instance();
// Find existing data
$data = $session->get('orders');
// Add new array
$data[] = array('id' => 3, 'name' => 'new data', 'price' => 300);
// Resave it
$session->set('orders', $data);
As for me, I think that best way:
public function before() {
...
$this->variable = Session::instance()->get('key', array());
...
}
some code...
public function after() {
...
Session::instance()->set('key', $this->variable, Date::MINUTE);
...
}

Resources