Laravel collection for loops and mappings - php

I am trying to refactor my code, and remove a for loop.
$result = [];
foreach ($data as $language) {
$result[$language->{$key}] = $language->{$column};
}
This became:
$result = $data->map(function($language) use ($key, $column){
return [$language->{$key} => $language->{$column}];
});
But now instead of:
[
"key":"value",
"key":"value"
]
I am getting
[
{
"key":"value"
},
{
"key":"value"
}
]
Why doesn't it map like an array?

Please refer this URL
For Example:
$emailLookup = $employees->reduce(function ($emailLookup, $employee) {
$emailLookup[$employee['email']] = $employee['name'];
return $emailLookup;
}, []);
Gives you result like:
const emailLookup = {
'john#example.com': 'John',
'jane#example.com': 'Jane',
'dave#example.com': 'Dave',
};
In your case do like:
$result = $data->reduce(function($language, $a){
$language[$a['any_you_want']] = $a['any_you_want'];
return $language;
}, []);
Hope this helps you!

You probably needed to mapWithKeys:
$result = $data->mapWithKeys(function($language) use ($key, $column){
return [$language->{$key} => $language->{$column}];
});
The method has been available since Laravel 5.3
According to the docs:
The mapWithKeys method iterates through the collection and passes each value to the given callback. The callback should return an associative array containing a single key / value pair:

For your simple use case, pluck() is the method you're looking for. It will build a new collection using one column of an existing array. You can also pass in a second field that will be used to key the new collection.
So, in your case, the data column you're selecting is $column, and the column to use as the key for the new collection is $key. Your code would be:
$result = $data->pluck($column, $key);
This says "give me a collection of all of the $column data, and key it by the $key data".
If you want the plain array instead of the collection, just call all() on the result:
$result = $data->pluck($column, $key)->all();
If you need to "pluck" more than one column of data, you will need to use the mapWithKeys() method already mentioned.

Here in loop you need to use as key value pair
$result = [];
foreach ($data as $key => $language) {
$result[$key] = $language;
}

Related

Laravel collection find common items

I am trying to find the common items existing in a collection like the following one:
I would like to end up with a new collection that contains the 928 and the 895 (common items between the key 95 and the key 94).
How can I do it?
I have an array of keys, but I don't understand how to loop over the keys AND the values without create a mess of variables and additional arrays:
foreach ($ids as $id) {
$item_ids->each(function ($item, $key) {
});
}
Well, I ended up with that solution:
$all = $item_ids->all();
$list = [];
foreach ($all as $single) {
$list[] = $single->toArray();
}
$commonItems = collect(call_user_func_array('array_intersect', $list));
So, this is a more laravel approach:
$items = $item_ids['items']->map(function ($item){
$collection[] = $item['items'];
return collect($collection)->duplicates();
});

how to search a array of objects with array property in laravel

i want query a table with a json column
the object stored in json column is like this:
[
{
"title":"first",
"ids":[79,583,584]
},
{
"title":"second",
"ids":[600,601,602]
},
{
"title":"third",
"ids":[605,606,624]
}
]
and for example i want to find a row where one of its ids property contain for example 79. something like this:
Model::query()->whereJsonContains('data', ['ids[*]' => 79])->first();
i,ve searched a lot and tried some syntaxes but nothing worked. is that possible to do? how?
my database is mysql
querying nested json formats might not be available as of now, you can try filtering the eloquent collection though.
you have to cast the json data column as array on your model first and then filter the collection as per your conditions.
$id = 8;
$filtered = Model::all()->filter(function($item, $key) use($id) {
$count = 0;
foreach($item->data as $data) {
if(in_array($id, $data['ids'])) {
$count += 1;
}
}
return $count > 0;
})->all();

push data in to a multidimensional array in laravel php

I want to create a multidimensional array to save the data according the date and a category as follow. Then i need to display this data in my blade view?what can i do to achieve this.
'2012-05-05' => array(
'suspension' => 52,
'transmission' => '58'
),
'2012-05-05' => array(
'suspension' => 44,
'transmission' => 21
I have done the following in my controller i want a $reportData variable to load the data.
public function loadReports(Request $request)
{
$data = ['2012-05-05','2012-05-06'];
$salesItems = array();
$orderItems = OrderItem::with('spare', 'order')->get();
foreach ($orderItems as $key => $orderItem) {
if ($orderItem->spare->retailer_id == Auth::user()->id) {
array_push($salesItems, $orderItem);
}
}
$categories = App\Categories::all();
foreach ($data as $date) {
foreach ($categories as $category) {
$categoryValue = 0;
foreach ($salesItems as $salesItem) {
if ($date == $salesItem->order->orderDate) {
$categoryValue += $categoryValue + $salesItem->subTotal;
}
}
//error appears as illegal offset type
$reportData[$date][$category]=$categoryValue;
}
}
return View::make('Retailer/reports')->with('categories', $categories)->with('reportData', $reportData);
}
I haven't tested it but looking at your code it seems that you're passing an object as array index key as 2nd level array index:
$reportData[$date][$category] = $categoryValue;
^^^^^^^^^ this is an object
Dump your $category in the foreach loop & check if that is the case: dd($category)
If you're using Eloquent & your Categories Model has a name property, you'll probably want to take each category name as index value:
$reportData[$date][$category->name] = $categoryValue;
The error is occurring due to the fact that you are trying to use an Object as the array's index.
As per the laravel documentation (https://laravel.com/api/4.2/Illuminate/Database/Eloquent/Model.html#method_all) the all method you called here '$categories = App\Category::all();' would have returned an Eloquent Collection.
So when you iterated over the $categories array and referenced $category, you were referencing an object. In PHP an array can only be indexed by either an integer or a string. So you need to change the line of code where the error is to this
$reportData[$date][$category->someVar] = $categoryValue;
Where someVar is the name of a variable on the Eloquent model Category that references its name, such as 'suspension' etc.
While it doesn't answer your question you could use the Eloquent engine to make your life easier:
$orderItems = OrderItem::with('spare', 'order')->get();
foreach ($orderItems as $key => $orderItem) {
if ($orderItem->spare->retailer_id == Auth::user()->id) {
array_push($salesItems, $orderItem);
}
}
can be simplified (and made more efficient) with:
// Store the uid to save the call.
$user_id = Auth::user()->id;
// Apply the condition to the Eloquent query.
$orderItems = OrderItem::with(['spare' => function($query) use ($user_id) {
return $query->where('retailer_id', '=', $user_id);
}, 'order'])->get();
The other answers are correct, but you probably also want to initialise the $reportData array as before you start working with it.

add data on a array query result

I have the function below in my model which return an array of data. I want to make another operation on each row and add the result to array of data before to return it.
function get_all_annonce()
{
$this->db->select(" * from annonce");
$this->db->order_by("annonce.DATEDEBUTANNONCE","asc");
$q=$this->db->get();
if($q->num_rows()>0)
{
foreach($q->result() as $row)
{
$data[]=$row;
//I try to add another result
$experience=$this->get_experience($row->NUMUSER);
$data['experience']=$experience;
}
return $data;
}
}
But I have an error when I try to access to $experience or $row->'experience' in my view. How can I fix it ?
The $data variable is defined in the wrong scope. You defined it inside the foreach loop but you try to return it after. Try adding $data = Array(); above the foreach.
In addition to the answer above.
First you have unnecessary assignments, you can do it in one line.
2nd - when you use [] - it will create index automatically and the row will be added as an array to that index. You get a multidimensional array( 0 => result 1, 1 => result 2 etc).
If you want to add the 'experience' key to the result, you cannot add it directly to data.
You get an array that will have keys 0,1,2,3,4 ... 'experience' as last key - each time it is overwritten.
One way would be to use a variable for key (or use for loop instead):
$i = 0;
foreach($q->result() as $row)
{
$data[$i]=$row;
$data[$i]['experience'] = $this->get_experience($row->NUMUSER);
}
If you used only [] for both, it would assign different key for each one every iteration.

Eloquent column list by key with array as values?

So I can do this with Eloquent:
$roles = DB::table('roles')->lists('title', 'name');
But is there a way to make Eloquent fetch an array of values for each distinct key instead of just one column?
For instance, something like the following:
$roles = DB::table('roles')->lists(['*', DB:raw('COALESCE(value, default_value)')], 'name');
You can use the keyBy method:
$roles = Role::all()->keyBy('name');
If you're not using Eloquent, you can create a collection on your own:
$roles = collect(DB::table('roles')->get())->keyBy('name');
If you're using Laravel 5.3+, the query builder now actually returns a collection, so there's no need to manually wrap it in a collection again:
$roles = DB::table('roles')->get()->keyBy('name');
If you need a key/value array, since Laravel 5.1 you can use pluck. This way you can indicate which attributes you want to use as a value and as a key.
$plucked = MyModel::all()->pluck(
'MyNameAttribute',
'MyIDAttribute'
);
return $plucked->all();
You will get an array as follow:
array:3 [▼
1 => "My MyNameAttribute value"
2 => "Lalalala"
3 => "Oh!"
]
You may try something like this:
$roles = array();
array_map(function($item) use (&$roles) {
$roles[$item->id] = (Array)$item; // object to array
}, DB::table('roles')->get());
If you want to get an Object instead of an Array as value then just remove the (Array).
Alternative: Using Eloquent model (Instead of DB::table):
$roles = array();
array_map(function($item) use (&$roles) {
$roles[$item['id']] = $item;
}, Role::all()->toArray());
Another Alternative: Using Collection::map() method:
$roles = array();
Role::all()->map(function($item) use(&$roles) {
$roles[$item->id] = $item->toArray();
});

Categories