Transform Laravel collection and group by key - php

I would like to transform a collection of object in laravel, but I can't figure it out how. I want to group the record by the type column, and set the grouped record under an array key value.
public function transformData()
{
$data = collect();
$matches = [ 'race', 'ethnicity'];
$attributes = Attribute::withTrashed()
->whereIn('type', $matches)
->get()
->groupBy('type');
$data->put(
$type, // to be the group key(like race)
[
'values' => $attributes->toArray(), // to be all the value with type race
]
);
dd(collect($data));
}
Here is what I'm getting:
Illuminate\Support\Collection^ {#2368
#items: array:1 [
"values" => array:2 [
"ethnicity" => array:2 [
0 => array:2 [
"id" => 1
"type" => "ethnicity"
]
1 => array:2 [
"id" => 2
"type" => "ethnicity"
]
]
"race" => array:2 [
0 => array:2 [
"id" => 6
"type" => "race"
]
1 => array:2 [
"id" => 7
"type" => "race"
]
]
]
]
#escapeWhenCastingToString: false
}
BUT I would like to return this instead:
Illuminate\Support\Collection^ {#2368
#items: array:1 [
"ethnicity" => array:2 [
"value" => array:2 [
0 => array:2 [
"id" => 1
"type" => "ethnicity"
]
1 => array:2 [
"id" => 2
"type" => "ethnicity"
]
]
]
"race" => array:2 [
"value" =>
0 => array:2 [
"id" => 6
"type" => "race"
]
1 => array:2 [
"id" => 7
"type" => "race"
]
]
]
#escapeWhenCastingToString: false
}

Related

recursive function transform nested array

Im my laravel project I have this nested array that needs to be updated (transformed - for the frontend):
array:2 [
0 => array:3 [
"entity_id" => 931
"entity" => "user"
"children" => array:2 [
0 => array:2 [
"entity_id" => 5
"entity" => "location"
]
1 => array:2 [
"entity_id" => 932
"entity" => "user"
]
]
]
1 => array:2 [
"entity_id" => 486
"entity" => "user"
]
]
EXPECTED ARRAY:
array:2 [
0 => array:4 [
"id" => 931
"text" => "Test User 1"
"type" => "user"
"children" => array:2 [
0 => array:3 [
"id" => 5
"text" => "Location 1"
"type" => "location"
]
1 => array:3 [
"id" => 932
"text" => "Test User 2"
"type" => "user"
]
]
]
1 => array:3 [
"id" => 486
"text" => "Test User 3"
"type" => "user"
]
]
I have created a recursive function for this job
public function getNewStructure($tree, &$output) {
foreach($tree as $data) {
$output[] = array(
'id' => $data['entity_id'],
'text' => $data['user'] === 'user' ? User::find($data['entity_id'])->name : Location::find($data['entity_id'])->name,
'type' => $data['entity']
);
$this->getNewStructure($data['children'] ?? [], $output);
}
return $output;
}
but it not returns as expected:
array:4 [
0 => array:3 [
"id" => 931
"text" => "Test User 1"
"type" => "user"
]
0 => array:3 [
"id" => 5
"text" => "Location 1"
"type" => "location"
]
1 => array:3 [
"id" => 932
"text" => "Test User 2"
"type" => "user"
]
1 => array:3 [
"id" => 486
"text" => "Test User 3"
"type" => "user"
]
]
How can I add the children to the $output array in the recursive function ???
I have tried by adding the children key:
$this->getNewStructure($data['children'] ?? [], $output['children']);
as when iterating again it will push the current array in the right place.... but is not working...
I fixed
public function getNewStructure($tree, &$output) {
foreach($tree as $data) {
$element = array(
'id' => $data['entity_id'],
'text' => $data['user'] === 'user' ? User::find($data['entity_id'])->name : Location::find($data['entity_id'])->name,
'type' => $data['entity']
);
if(is_array($data['children']) && count($data['children']) > 0) {
$element['children'] = $this->getNewStructure($data['children'], $element['children']);
}
$output[] = $element;
}
return $output;
}

Use multiple Index search in multiple fields in Elasticsearch

This is my search query. Here I am trying to search inside two different fields of two different index but it is giving result from one index only
array:2 [
"index" => "items-123-*,asso-456-*"
"body" => array:1 [
"query" => array:1 [
"bool" => array:1 [
"should" => array:2 [
0 => array:1 [
"match" => array:1 [
"title" => "Civics"
]
]
1 => array:1 [
"match" => array:1 [
"type" => "matchOf"
]
]
]
]
]
]
]
I tried below way but not working
array:1 [
"body" => array:1 [
"query" => array:1 [
"bool" => array:1 [
"should" => array:2 [
0 => array:2 [
"term" => array:1 [
"_index" => "items-123-123"
]
"match_phrase" => array:1 [
"title" => "Civics"
]
]
1 => array:2 [
"term" => array:1 [
"_index" => "cfassociations-345-*"
]
"match_phrase" => array:1 [
"type" => "matchOf"
]
]
]
]
]
]
]
Use alias to search for multiple index. For index items-123-*
POST _aliases
{
"actions": [
{
"add": {
"index": "items-123-*",
"alias": "my-new-index"
}
}
]
}
And for index asso-456-*
POST _aliases
{
"actions": [
{
"add": {
"index": "asso-456-*",
"alias": "my-new-index"
}
}
]
}
Now you can search by using the alias name my-new-index.

Laravel 8: Sorting grouped array by a nested column - what should I put into sortBy closure?

I'm dealing with a specifically shaped array in Laravel where items are grouped by keys that represent names of categories.
In below example I have elements from categories 1, 5 and 76. Each element has a key called order which is a nullable integer that should indicate the order within this category.
array:3 [
"category_1" => array:4 [
1 => array:2 [
"option_name" => "Some name 1"
"option_items" => array:1 [
0 => array:5 [
"id" => 1
"price" => 200
"time" => 0
"order" => 999
]
]
]
2 => array:2 [
"option_name" => "Some name 2"
"option_items" => array:1 [
0 => array:5 [
"id" => 2
"price" => 780
"time" => 5
"order" => null
]
]
]
3 => array:2 [
"option_name" => "Some name 3"
"option_items" => array:1 [
0 => array:5 [
"id" => 3
"price" => 400
"time" => 4
"order" => null
]
]
]
4 => array:2 [
"option_name" => "Some name 4"
"option_items" => array:1 [
0 => array:5 [
"id" => 4
"price" => 300
"time" => 2
"order" => 434
]
]
]
]
"category_5" => array:2 [
6 => array:2 [
"option_name" => "Some name 5"
"option_items" => array:1 [
0 => array:5 [
"id" => 6
"price" => 890
"time" => 3
"order" => null
]
]
]
7 => array:2 [
"option_name" => "Some name 6"
"option_items" => array:1 [
0 => array:5 [
"id" => 7
"price" => 1290
"time" => 5
"order" => null
]
]
]
]
"category_76" => array:2 [
10 => array:2 [
"option_name" => "Some name 7"
"option_items" => array:1 [
0 => array:5 [
"id" => 10
"price" => 320
"time" => 4
"order" => 33
]
]
]
11 => array:2 [
"option_name" => "Some name 8"
"option_items" => array:2 [
0 => array:5 [
"id" => 11
"price" => 600
"time" => 0
"order" => 500
]
1 => array:5 [
"id" => 12
"price" => 2000
"time" => 9
"order" => 500
]
]
]
]
]
I simply want to sort this entire array per category by order key ascending (with nulls at the end), so for example the order of elements in category_1 would be:
Some name 4 (order of 434)
Some name 1 (order of 999)
Some name 2 (order is nor present / null)
Some name 3 (same as above)
What did you try?
Obviously I've tried converting this plain PHP array to collection and calling sortBy with a closure via:
$sorted = collect($array)->sortBy(function ($elementsInCategory, $key) {
dd($elementsInCategory); // $key is category_1
})->toArray();
but I simply don't know what to return from the callback to make it sort the way I've described.
BTW. I don't want to complicate too much but please notice that option_items sub-array may sometimes have more than one item (key 11 from category_76) but this does not matter - elements in this sub array will always have the same order value. This inner array should not be sorted - can be left as is.
You can use Laravel collection macro for that
$Collection::macro('sortByOrder', function (string $column = 'order', bool $descending = false) {
/* #var $this Collection */
return $this->sortBy(function ($order) use ($column) {
return strtotime(((object)$order)->$column);
}, SORT_REGULAR, $descending);
});
And you can use it like
$categories->sortByOrder('order',false);

How to get value from unserialized data

I'm transforming my data into an array structure. Now I have the meta which already unserialized and I just need to take a specific value in meta.
Code
$item->meta;
$itm['attrs'] = #unserialize($item->meta);
$serial = #unserialize($item->meta);
$itm['product']['attrs'] = $itm['attrs'];
$itm['product']['serial'] = $serial['serial'];
Result
"product" => array:2 [
"attrs" => array:1 [
"serial" => array:1 [
0 => array:3 [
"id" => 848
"text" => "12345wf"
"trade_in" => 0
]
]
]
"serial" => array:1 [
0 => array:3 [
"id" => 848
"text" => "12345wf"
"trade_in" => 0
]
]
]
Expected Result
"product" => array:2 [
"attrs" => array:1 [
"serial" => array:1 [
0 => array:3 [
"id" => 848
"text" => "12345wf"
"trade_in" => 0
]
]
]
"serial" => "12345wf"
]
I'm not sure how to get the value and pass to the object.

ResultSetMapping addScalarResult associative array

In my project with Symfony2, I'm using Doctrine createNativeQuery, and I would like to get an associative array.
This is my code
$rsm = new ResultSetMapping;
$rsm->addScalarResult('id', 'id');
$rsm->addScalarResult('name', 'name');
$rsm->addScalarResult('phone_one', 'phoneOne');
$rsm->addScalarResult('phone_two', 'phoneTwo');
I have this result:
array:2 [
0 => array:4 [
"id" => "975"
"name" => "one name"
"phoneOne" => "122345556"
"phoneTwo" => "345566789"
]
1 => array:4 [
0 => array:4 [
"id" => "976"
"name" => "two name"
"phoneOne" => "122345556"
"phoneTwo" => "345566789"
]
]
It's posible this result?
array:2 [
0 => array:4 [
"id" => "975"
"name" => "one name"
"phones" => [
"phoneOne" => "122345556"
"phoneTwo" => "345566789"
]
]
1 => array:4 [
0 => array:4 [
"id" => "976"
"name" => "two name"
"phones" => [
"phoneOne" => "122345556"
"phoneTwo" => "345566789"
]
]
]
Thanks a lot
If that is the result you want, why not create a OneToMany for Users to Phones? I would highly suggest you do that.

Categories