I have to models in a OneToMany relashionship and i've done a ORM query to get the result in a nested structure like this : $u->userGroups()->with('space')->get()
and i've go the following result :
Illuminate\Database\Eloquent\Collection {#3158
all: [
App\UserGroup {#3142
role: "CONTRIBUTORS",
updated_at: "2019-04-06 16:38:43",
name: "Contributeurs",
created_at: "2019-04-06 16:38:43",
slug: "contributeurs",
id: 789,
space: App\Space {#3180
country: "Congo-Kinshasa",
address: "40 rue Zozo",
visibility: "public",
town: "Kinshasa",
updated_at: "2019-04-06 16:38:42",
name: "Christian Lisangola",
logo: "spaces/48fcacca888f0b35235b9edda371554dcfc2afc0.png",
created_at: "2019-04-06 16:38:42",
zip_code: "5767",
slug: "christian-lisangola",
id: 850,
},
},
App\UserGroup {#3145
role: "AUTHORS",
updated_at: "2019-04-06 16:38:43",
name: "Auteurs",
created_at: "2019-04-06 16:38:43",
slug: "auteurs",
id: 788,
space: App\Space {#3185
country: "Congo-Kinshasa",
address: "40 rue Luiss",
visibility: "public",
town: "Kinshasa",
updated_at: "2019-04-06 16:38:42",
name: "Christian Lisangola",
logo: "spaces/48fcacca888f0b35235b9edda371554dcfc2afc0.png",
created_at: "2019-04-06 16:38:42",
zip_code: "5767",
slug: "christian-lisangola",
id: 850,
},
},
App\UserGroup {#3148
role: "ADMINISTRATORS",
updated_at: "2019-04-06 16:37:37",
name: "Administrateurs",
created_at: "2019-04-06 16:37:37",
slug: "administrateurs",
id: 848,
space: App\Space {#3170
country: "États-Unis",
address: "100 avenue zazi",
town: "Houston",
visibility: "on_demand",
updated_at: "2019-04-06 16:37:37",
name: "US",
logo: "spaces/8490c3a93d32951d3d8d0ade7c459c70b202c342.png",
created_at: "2019-04-06 16:37:37",
zip_code: "33234",
slug: "us",
id: 766,
},
},
App\UserGroup {#3151
role: "ADMINISTRATORS",
updated_at: "2019-04-06 16:37:11",
name: "Administrateurs",
created_at: "2019-04-06 16:37:11",
slug: "administrateurs",
id: 765,
space: App\Space {#3175
country: "États-Unis",
address: "100 avenue zozo",
town: "Houston",
visibility: "private",
updated_at: "2019-04-06 16:37:11",
name: "Lims INC",
logo: "spaces/4f1c5ac285bbc38919133b83de58ac1f7802fea4.png",
created_at: "2019-04-06 16:37:11",
type: "private",
zip_code: "343",
slug: "lims-inc",
id: 844,
},
},
App\UserGroup {#3154
role: "ADMINISTRATORS",
updated_at: "2019-04-06 16:36:33",
name: "Administrateurs",
created_at: "2019-04-06 16:36:33",
slug: "administrateurs",
id: 1,
space: App\Space {#3165
country: "États-Unis",
address: "100 avenue zozo",
visibility: "public",
town: "Houston",
updated_at: "2019-04-06 16:36:33",
name: "Gravity",
logo: "spaces/4dab5e2bf8d8725b05186b9d574f8c98640526d9.png",
created_at: "2019-04-06 16:36:33",
zip_code: "111",
slug: "gravity",
id: 0,
},
},
],
I would like to have a structure in which i have an paire-key value array in this format : ["space.id"=>"role"]
and if for a given space.id
they key is duplicated,it should create an array like this ['space.id'=>[role1,role2]]
.To try to soleve the problem i've used the pluck method on Laravel collections.But there is 2 main problems. The result of the previous array has been kept in the $result
variable.And on that variable i've called the pluck method like this :$result->pluck('role','space.id')->all()
an then i got this:
[
850 => "AUTHORS",
766 => "ADMINISTRATORS",
844 => "ADMINISTRATORS",
0 => "ADMINISTRATORS",
]
First of all,when i do this in tinker everything goes fine.But when i put the result in a json
format to send in the front-end
,the space.id
doesn't appear,and this is how it looks after a ajax call
:
[
"0" => "AUTHORS",
"1" => "ADMINISTRATORS",
"2" => "ADMINISTRATORS",
"3" => "ADMINISTRATORS",
]
So,i don't know why the original space.id
is not present.
Second problem:If you look carefully at the first array the space.id 850
it reapeted twice,for CONTRIBUTORS
and for AUTHORS
,so it doesn't support duplicate keys
and it has took the latest value for the same key 850
.But what i would like to have is something like this for duplicate keys:
[
850 => ["CONTRIBUTORS","AUTHORS"],//Take the 2 instead of only keep the latest value
766 => "ADMINISTRATORS",
844 => "ADMINISTRATORS",
0 => "ADMINISTRATORS",
]
But i don't have any solution.Thank you
My answer would rely on Laravel collections, but you could adapt it to filter the results at query level (as it would be faster), but for small sets of data it's fine enough to process them with php.
Note that JSON doesn't allow for array keys to have unsequential integer keys, so each [id => roles[]]
mapping would become an object, and your output would be:
{
"850": ["CONTRIBUTORS","AUTHORS"],
"766": ["ADMINISTRATORS"],
"844": ["ADMINISTRATORS"],
"0": ["ADMINISTRATORS"]
}
To transform your query results into that json output you have to process it like that:
// Query the database
$groups = $u->userGroups()->with('space')->get();
$roles = $groups->groupBy(function ($group) {
// Group each 'UserGroup' by space.id
return $group->space->id;
})->map(function ($group) {
// For each group created, pluck the roles
return $group->pluck('role');
});
dd($roles->toJson());
Note: if your scope is to return the data to the caller as json, you could also decide to use return response()->json($roles)
instead of converting it to json and print as a string.