Laravel - why json response return sometimes an array sometimes an object - javascript

Here is my code :
public function list()
{
$users = User::with('group')->get()->toArray();
return response()->json([
'clients' => array_filter($users, function ($r) {
return $r['group']['name'] === 'client';
}),
'employes' => array(array_filter($users, function ($r) {
return $r['group']['name'] !== 'client';
})),
]);
}
Here is the response :
{
"clients": {
"2": {
"id": 3,
"name": "Client 1",
"email": "client#a.fr",
"email_verified_at": null,
"created_at": null,
"updated_at": null,
"group_id": 4,
"group": {
"id": 4,
"name": "client"
}
},
"3": {
"id": 4,
"name": "Client 2",
"email": "client2#a.fr",
"email_verified_at": null,
"created_at": null,
"updated_at": null,
"group_id": 4,
"group": {
"id": 4,
"name": "client"
}
},
"4": {
"id": 5,
"name": "Client 3",
"email": "client3#a.fr",
"email_verified_at": null,
"created_at": null,
"updated_at": null,
"group_id": 4,
"group": {
"id": 4,
"name": "client"
}
}
},
"employes": [
[
{
"id": 1,
"name": "Alexis",
"email": "alexis#a.fr",
"email_verified_at": null,
"created_at": null,
"updated_at": null,
"group_id": 1,
"group": {
"id": 1,
"name": "admin"
}
},
{
"id": 2,
"name": "guest",
"email": "guest#a.fr",
"email_verified_at": null,
"created_at": null,
"updated_at": null,
"group_id": 2,
"group": {
"id": 2,
"name": "guest"
}
}
]
]
}
I tried to change the conditions of the array_filter. Sometimes I have an array, sometimes I have an object. I don't understand how this is determined
Stackoverflow tells me "It looks like your post is mostly code; please add some more details." So ... what details to add?
Thank you

Internally array_filter() filters matching entries from the array, and returns them with their indices intact. This is very important, as it is the core reason you're getting an object and not an array in JavaScript.
In PHP, this is fine; arrays can start at 0, or another index, such as 2, and function as an array without issue. This is due to the existence of indexed (0-based) and associative (numeric/non-numeric key based) arrays.
In JavaScript, arrays cannot be "associative", i.e. they must start at 0. object classes on the other hand function similarly to associative arrays, but the key difference is that they aren't explicitly arrays.
Now that you know the why, the next question is "how do I fix this?" The simple method is to wrap array_filter() with a function that simply returns the values of the new array. This inherently will "re-index" the array with 0-based values, which when converted to JSON will result in correct arrays being returned:
$users = User::with('group')->get()->toArray();
$clients = array_filter($users, function($r){
return $r['group']['name'] === 'client';
});
$groups = array_filter($users, function ($r) {
return $r['group']['name'] !== 'client';
});
return response()->json([
'clients' => array_values($clients),
'groups' => array_values($groups)
]);
As a sidenote, Collection classes have similar logic, and I prefer to use Laravel's Collection class whenever possible:
$users = User::with('group')->get();
$clients = $users->filter(function($r){
$r->group->name === 'client';
});
$groups = $users->filter(function($r){
$r->group->name !== 'client';
});
return response()->json([
'clients' => $clients->values(),
'groups' => $groups->values()
]);
But again, that's my preference; either approach should work, so use what you're used to.
References:
PHP Array Methods:
https://www.php.net/manual/en/function.array-filter.php
https://www.php.net/manual/en/function.array-values.php
Laravel Collection Methods:
https://laravel.com/docs/5.8/collections#method-filter
https://laravel.com/docs/5.8/collections#method-values

This works for me. I hope this will help anyone.
return response(['STATUS'=>'true','message'=>'Your Message','response'=>
array_values('clients' => array_filter($users, function ($r) {
return $r['group']['name'] === 'client';
})),
'employes' => array_values(array_filter($users, function ($r) {
return $r['group']['name'] !== 'client';
}))
)]);
If in response array you will get a result like an index key and you want the response in object array [{ ... }] then use array_values() will resolve your problem.
"clients": {
"2": {
"id": 3,
"name": "Client 1",
"email": "client#a.fr",
"email_verified_at": null,
"created_at": null,
"updated_at": null,
"group_id": 4,
"group": {
"id": 4,
"name": "client"
}
},

simply add ->values() it will reorder array keys
users = User::with('group')->values();

Related

Laravel Sorted Collection Gets Undone When Passed to Javascript [duplicate]

Here is my code :
public function list()
{
$users = User::with('group')->get()->toArray();
return response()->json([
'clients' => array_filter($users, function ($r) {
return $r['group']['name'] === 'client';
}),
'employes' => array(array_filter($users, function ($r) {
return $r['group']['name'] !== 'client';
})),
]);
}
Here is the response :
{
"clients": {
"2": {
"id": 3,
"name": "Client 1",
"email": "client#a.fr",
"email_verified_at": null,
"created_at": null,
"updated_at": null,
"group_id": 4,
"group": {
"id": 4,
"name": "client"
}
},
"3": {
"id": 4,
"name": "Client 2",
"email": "client2#a.fr",
"email_verified_at": null,
"created_at": null,
"updated_at": null,
"group_id": 4,
"group": {
"id": 4,
"name": "client"
}
},
"4": {
"id": 5,
"name": "Client 3",
"email": "client3#a.fr",
"email_verified_at": null,
"created_at": null,
"updated_at": null,
"group_id": 4,
"group": {
"id": 4,
"name": "client"
}
}
},
"employes": [
[
{
"id": 1,
"name": "Alexis",
"email": "alexis#a.fr",
"email_verified_at": null,
"created_at": null,
"updated_at": null,
"group_id": 1,
"group": {
"id": 1,
"name": "admin"
}
},
{
"id": 2,
"name": "guest",
"email": "guest#a.fr",
"email_verified_at": null,
"created_at": null,
"updated_at": null,
"group_id": 2,
"group": {
"id": 2,
"name": "guest"
}
}
]
]
}
I tried to change the conditions of the array_filter. Sometimes I have an array, sometimes I have an object. I don't understand how this is determined
Stackoverflow tells me "It looks like your post is mostly code; please add some more details." So ... what details to add?
Thank you
Internally array_filter() filters matching entries from the array, and returns them with their indices intact. This is very important, as it is the core reason you're getting an object and not an array in JavaScript.
In PHP, this is fine; arrays can start at 0, or another index, such as 2, and function as an array without issue. This is due to the existence of indexed (0-based) and associative (numeric/non-numeric key based) arrays.
In JavaScript, arrays cannot be "associative", i.e. they must start at 0. object classes on the other hand function similarly to associative arrays, but the key difference is that they aren't explicitly arrays.
Now that you know the why, the next question is "how do I fix this?" The simple method is to wrap array_filter() with a function that simply returns the values of the new array. This inherently will "re-index" the array with 0-based values, which when converted to JSON will result in correct arrays being returned:
$users = User::with('group')->get()->toArray();
$clients = array_filter($users, function($r){
return $r['group']['name'] === 'client';
});
$groups = array_filter($users, function ($r) {
return $r['group']['name'] !== 'client';
});
return response()->json([
'clients' => array_values($clients),
'groups' => array_values($groups)
]);
As a sidenote, Collection classes have similar logic, and I prefer to use Laravel's Collection class whenever possible:
$users = User::with('group')->get();
$clients = $users->filter(function($r){
$r->group->name === 'client';
});
$groups = $users->filter(function($r){
$r->group->name !== 'client';
});
return response()->json([
'clients' => $clients->values(),
'groups' => $groups->values()
]);
But again, that's my preference; either approach should work, so use what you're used to.
References:
PHP Array Methods:
https://www.php.net/manual/en/function.array-filter.php
https://www.php.net/manual/en/function.array-values.php
Laravel Collection Methods:
https://laravel.com/docs/5.8/collections#method-filter
https://laravel.com/docs/5.8/collections#method-values
This works for me. I hope this will help anyone.
return response(['STATUS'=>'true','message'=>'Your Message','response'=>
array_values('clients' => array_filter($users, function ($r) {
return $r['group']['name'] === 'client';
})),
'employes' => array_values(array_filter($users, function ($r) {
return $r['group']['name'] !== 'client';
}))
)]);
If in response array you will get a result like an index key and you want the response in object array [{ ... }] then use array_values() will resolve your problem.
"clients": {
"2": {
"id": 3,
"name": "Client 1",
"email": "client#a.fr",
"email_verified_at": null,
"created_at": null,
"updated_at": null,
"group_id": 4,
"group": {
"id": 4,
"name": "client"
}
},
simply add ->values() it will reorder array keys
users = User::with('group')->values();

Partial selection on Inner Join

I need select ony on field to services, look:
async find(): Promise<AccountEntity[]> {
const result = await this.repository
.createQueryBuilder("account")
.select(['account', 'accountServices', 'service.description'])
.leftJoinAndSelect("account.accountAndServices", "accountServices")
.leftJoinAndSelect("accountServices.service", "service")
.getMany();
return result === undefined ? null : result;
}
How to ? please.
I don't want null attributes to appear and I also want to choose which attributes to show
I need :
{
"message": "",
"success": true,
"data": [
{
"id": 1,
"name": "STONES TECNOLOGIA LTDA",
"accountAndServices": [
{
"service": {
"name": "Construção de uma casa",
},
"date_initial": "2021-08-01T07:39:18.000Z",
"date_final": "2021-08-01T07:39:20.000Z",
"value": "10.00",
"created_by": 1,
"is_active": true,
"id": 1,
"pay_day": 10,
"nfse": 0,
"created_at": "2021-08-01T07:39:27.000Z",
},
{
"service": {
"name": "Desenvolvimento de sistemas",
},
"date_initial": "2021-08-01T07:40:01.000Z",
"date_final": "2021-08-01T07:40:02.000Z",
"value": "20.00",
"created_by": 1,
"is_active": true,
"id": 2,
"pay_day": 20,
"nfse": 0,
"created_at": "2021-08-01T07:40:11.000Z",
}
]
}
],
"errors": null
}
I Need selection only field on entity join.
Select with innerJoin you must use addSelect(...).
The find function must not manipulate any data and should return an array of AccountEntity (empty if not found):
function find(): Promise<AccountEntity[]> {
return this.repository
.createQueryBuilder("a")
.innerJoin("account.accountAndServices", "as")
.innerJoin("accountServices.service", "s")
.select(['a.id', 'a.name', 'a.status'])
.addSelect(['as.date_initial', 'as.date_final', 'as.service_id', 'as.value', 'as.nfse', 'as.value', 'as.created_by', 'is_active', 'pay_day', 'created_at'])
.addSelect(['s.name'])
.getMany();
}
Note that to obtain the result from the function you must use await.
Moreover, surround it with try and catch for a better error handling.
Example:
try {
const accounts: AccountEntity[] = await find();
} catch(error) {
console.error(`Error: ${error}`);
}
To transform the array of AccountEntity to another object:
function transform(accounts?: AccountEntity[]) {
return {
message: "",
success: accounts !== undefined,
data: accounts,
errors: null
};
}

Javascript For Each Object inside Array containing a property that is Array check If Value Matches

For each object inside this array containing userHandle array loop through that array(userHandle one) and check if one of those values matches some string I choose called uid. How to write that code in Javascript?
Array [
Object {
"avatar": null,
"hugCount": 2,
"id": 35,
"liked": false,
"name": "fhfdhdhf",
"text": "Yoho",
"timestamp": 1610471860157,
"uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1",
},
Object {
"avatar": null,
"hugCount": 1,
"id": 34,
"liked": true,
"mood": 2,
"name": "fhfdhdhf",
"text": "I'm fine today.",
"timestamp": 1607943705709,
"uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1",
"userHandle": Array [
"Aw8AUj1mPkON1Fd1s6LhkNETHfb2",
"LrIwIx9I1xQBJ7aeCSrinpEaDP53",
],
}]
Try this code:
var uid = "LrIwIx9I1xQBJ7aeCSrinpEaDP53";
yourArray.forEach(function(item, _){
return item['userHandle']?.indexOf(uid);
});
The '?' is to make sure your Object contains the 'userHandle' property
This is the function you need... and below you can see how to use it.
You need to pass the value you are looking for, and the array with the information.
function findInUserHandle(uidValue, array)
{
return array.reduce
(
(acum, current) =>
current.userHandle && current.userHandle.indexOf(uidValue) !== -1 || acum,
false
)
}
let array = [
{
"avatar": null,
"hugCount": 2,
"id": 35,
"liked": false,
"name": "fhfdhdhf",
"text": "Yoho",
"timestamp": 1610471860157,
"uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1",
},
{
"avatar": null,
"hugCount": 1,
"id": 34,
"liked": true,
"mood": 2,
"name": "fhfdhdhf",
"text": "I'm fine today.",
"timestamp": 1607943705709,
"uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1",
"userHandle":[
"Aw8AUj1mPkON1Fd1s6LhkNETHfb2",
"LrIwIx9I1xQBJ7aeCSrinpEaDP53",
],
}
]
findInUserHandle('something', array) //? false
findInUserHandle('Aw8AUj1mPkON1Fd1s6LhkNETHfb2', array) //? true
findInUserHandle('mood', array) //? false

React-Native remove object from Array

I'm trying to remove an object from the array, even though, I'm not sure how to grab the object, which basically makes the code that is written not make anything.
Let me show the existing array:
Object {
"created_at": "2020-06-30T11:22:53.000000Z",
"icon": "subjectImgs/509-1080x1080.jpg",
"id": 2,
"name": "Test",
"updated_at": "2020-06-30T11:22:53.000000Z",
"user_id": 1,
},
Object {
"created_at": "2020-06-04T18:32:25.000000Z",
"icon": "subjectImgs/698-1080x1080.jpg",
"id": 1,
"name": "history",
"updated_at": "2020-06-04T18:32:25.000000Z",
"user_id": 1,
},
Object {
"created_at": "2020-07-08T16:32:03.000000Z",
"icon": "subjectImgs/698-1080x1080.jpg",
"id": 21, // Here is the ID
"name": "123",
"updated_at": "2020-07-08T16:32:03.000000Z",
"user_id": 1,
},
}
When the event is listened to, I get the array of the object that was just deleted:
Object {
"socket": null,
"subject": Object {
"created_at": "2020-07-08T16:32:03.000000Z",
"icon": "subjectImgs/698-1080x1080.jpg",
"id": 21, // Here is the ID
"name": "123",
"updated_at": "2020-07-08T16:32:03.000000Z",
"user_id": 1,
},
}
Now, the way I'm trying to delete it is the following:
.listen('SubjectRemoved', ev => {
var array = this.state.subjects
this.setState({ subjects: array.filter((id) => id != ev.subject.id) })
});
but apparently, this is not working. I assume because of using id really gets nothing.
I think that the problem is in the filter method:
array.filter((id) => id != ev.subject.id) // here id is an elemt of the array not the real id
You could try
array.filter((subject) => subject.id != ev.subject.id) //if is an array of subjects
or
array.filter((elem) => elem.subject.id != ev.subject.id) //if is an array of objects like {socket: null, subject: {... with the fields }}
If you think that the ev.subject.id is not working you could just console.log it before the filter senetence.

How to remove certain key value pairs form a Object

I have used Lodash to get to this structure where i needed to group by id .
The grouping by works fine but i want to add more properties to the head of the group by field like its name and domain, from the nested object , how do i do that.
Extra - Also In future if i need to Filter the contents inside the nested object like using status or by the publisher name how do i add that . Very new to Javascript
let result = _.chain(value)
.groupBy('pubId')
.pairs()
.map(function(currentItem) {
return _.object(_.zip(['publisherId', 'targetting'], currentItem));
})
.value();
The data returned by this
{
"publisherId": "17",
// add name , domain , here
"targetting": [
{
"id": 1,
"pubId": 17, // remove this
"type": 18,
"value": "google.com,yahoo.com",
"status": 12,
"createTs": null, // remove this
"updateTs": null,// remove this
"createUser": null,// remove this
"updateUser": null,// remove this
"percentage": 0,// remove this
"rtbSspPublishers": { // remove this
"id": 17,
"name": "Tom's Hardware",
"domain": "www.tomshardware.com",
"extPublisherId": 17
}
},
{
"id": 2,
"pubId": 17,
"type": 14,
"value": "Sports,Fashion",
"status": 12,
"createTs": null,
"updateTs": null,
"createUser": null,
"updateUser": null,
"percentage": 0,
"rtbSspPublishers": {
"id": 17,
"name": "Tom's Hardware",
"domain": "www.tomshardware.com",
"extPublisherId": 17
}
},
{
"id": 3,
"pubId": 17,
"type": 11,
"value": "Sports,Fashion",
"status": 12,
"createTs": null,
"updateTs": null,
"createUser": null,
"updateUser": null,
"percentage": 0,
"rtbSspPublishers": {
"id": 17,
"name": "Tom's Hardware",
"domain": "www.tomshardware.com",
"extPublisherId": 17
}
}
]
}
I need to remove certain properties from the nested grouping how do i acheive that using lodash i am using lodash 3.0.0 .Please help thanks
Just iterate the result again and delete those properties which are not required.
For example
var propsToBeDeleted = [ "createTs", "updateTs" ]; //array of properties to be deleted
result = result.map( function(item){
propsToBeDeleted.forEach( function(prop){
delete item[prop];
});
return item;
});
Or try updating your lodash code as
let result = _.chain(value)
.groupBy('pubId')
.pairs()
.map(function(currentItem) {
var item = _.object(_.zip(['publisherId', 'targetting'], currentItem));
propsToBeDeleted.forEach( function(prop){
delete item[prop];
});
return item;
})
.value();

Categories