Laravel 8 hasManyThrough Iteration - iteration

I have just started my journey with Laravel and PHP.
I have this route:
Route::get('/admin/applications/staff-role', function () {
$staff = StaffRole::with('applications')->where('id', '=', '1')->get();
return $staff;
});
which is the result of hasManyThrough query and returns this result:
[
{
"id": 1,
"staff_role_label": "Staff 1",
"staff_role_description": "Staff Role 1",
"staff_role_abbreviation": "SR1",
"deleted_at": null,
"applications": [
{
"id": 1,
"vacancy_id": 1,
"hours_per_week": "9",
"contract_type": "Full-Time",
"desired_shift_option": "Weekends",
"name": "John",
"surname": "Doe",
"mobile_phone_number": "07911 123456",
"email": "test1#test.com",
"application_status": 1,
"is_staff": 1,
"staff_status": 0,
"deleted_at": null,
"laravel_through_key": 1
},
{
"id": 2,
"vacancy_id": 1,
"hours_per_week": "9",
"contract_type": "Full-Time",
"desired_shift_option": "Weekends",
"name": "Jane",
"surname": "Doe",
"mobile_phone_number": "07911 123456",
"email": "test2#test.com",
"application_status": 1,
"is_staff": 1,
"staff_status": 0,
"deleted_at": null,
"laravel_through_key": 1
}
]
}
]
So far, so good, but how can I count how many applications I have in the array?
Thanks.

Related

Laravel Eloquent Collection filter by pivot id

This is my Apartment integrated with services
"id": 26,
"user_id": 1,
"title": "SAN MARINO",
"slug": "san-marino",
"rooms": 1,
"bathrooms": 1,
"beds": 1,
"squared_meters": 12,
"address": "San Marino, Carpi",
"latitude": "44.80924",
"longitude": "10.91565",
"image": "apartment_image/BMRQZSXLdWviqDwmHgqLzrmzG1hJzJGOq7DujnRB.jpg",
"is_visible": 1,
"floor": 1,
"price": 120,
"description": "2",
"created_at": "2022-02-21T21:41:53.000000Z",
"updated_at": "2022-02-21T21:41:53.000000Z",
"services": [
{
"id": 2,
"name": "Posto Macchina",
"slug": "posto-macchina",
"created_at": "2022-02-21T08:59:53.000000Z",
"updated_at": "2022-02-21T08:59:53.000000Z",
"pivot": {
"apartment_id": 26,
"service_id": 2
}
}
]
}
I use to filter my collection( $apartment_list = ApartmentResource::collection(Apartment::with(['services'])->get());)
using multiple WHERE, like this: $apartment_list = $apartment_list->where('rooms', '>=', $rooms);
How can i filter my Apartment refering to the pivot column service_id or services[id]?
There is filter method for the collection. You may create a callback for a single apartament and filter in any way you want:
$apartment_list->filter(function ($apartament) {
// ...
});
you can use try with this:
$serviceId = value_of_service_id;
$apartment_list = ApartmentResource::collection(Apartment:: whereHas('services', function ($q) use ($serviceId) {
$q->where('service_id', $serviceId);
})->get());

Nested Join with aggregation in posgres

In my DB, there are two tables
EventType
ID (Primary key)
Name
ActivityType
ID (Primary key)
Name
EventTypeID (foreign key)
ParentActivityTypeID (Relation with self ID)
I have tried with the following query to aggregate the json
SELECT coalesce(json_build_object(
'EventTypeID', ev."ID",
'EventTypeName', ev."Name",
'ActivityType', json_agg(json_build_object('ID',ac."ID",'Name',ac."Name",'ParentActivityType',json_agg(select * from "Activity" where ))
), '{}'::json) AS item
FROM "EventType" as ev
JOIN "ActivityType" as ac ON ev."ID" = ac."EventTypeID"
GROUP BY ev."ID"
expected JSON output
[{
"EventTypeID": 2,
"EventTypeName": "On-Site Care",
"ActivityType": [
{
"ID": 1,
"Name": "Measurement",
"EventTypeID": 2,
"ParentActivityTypeID": null,
"SubActivityType": [
{
"ID": 17,
"Name": "abc",
"EventTypeID": 2,
"ParentActivityTypeID": 1
}
]
},
{
"ID": 2,
"Name": "Medication",
"EventTypeID": 2,
"ParentActivityTypeID": null
},
{
"ID": 3,
"Name": "Wellness check",
"EventTypeID": 2,
"ParentActivityTypeID": null
},
{
"ID": 4,
"Name": "Other",
"EventTypeID": 2,
"ParentActivityTypeID": null
}
]
},
{
"EventTypeID": 3,
"EventTypeName": "Care Call",
"ActivityType": [
{
"ID": 1,
"Name": "Measurement",
"EventTypeID": 3,
"ParentActivityTypeID": null,
"SubActivityType": [
{
"ID": 17,
"Name": "abc",
"EventTypeID": 3,
"ParentActivityTypeID": 1
}
]
},
{
"ID": 2,
"Name": "Medication",
"EventTypeID": 3,
"ParentActivityTypeID": null
},
{
"ID": 3,
"Name": "Wellness check",
"EventTypeID": 3,
"ParentActivityTypeID": null
},
{
"ID": 4,
"Name": "Other",
"EventTypeID": 3,
"ParentActivityTypeID": null
}
]
}
]
You can join self table as parent described as below.
SELECT coalesce(json_build_object(
'EventTypeID', ev."ID",
'EventTypeName', ev."Name",
'ActivityType', json_agg(json_build_object('ID',ac."ID",'Name',ac."Name",'ParentActivityType',json_agg(parent.*))
), '{}'::json) AS item
FROM "EventType" as ev
LEFT JOIN "EventType" as parent ON ev."ParentActivityTypeID" = parent."ID"
JOIN "ActivityType" as ac ON ev."ID" = ac."EventTypeID"
GROUP BY ev."ID"

Add virtual column for order by it but does not return it

I have an entity which has a point (postgis) property.I need to return a collection of that entity ordered by the distance between coordinates of user and the point of entity.
For this, Im adding an aggregate function for calculate that distance and add it in ORDER BY, but I dont want to return it. I only need that return and array of objects of entity.
Without order by, the result is:
[
{
"user": "/api/users/1",
"id": 1,
"gender": "MALE",
"createdAt": "2019-04-05T11:03:03+02:00",
"updateAt": "2019-04-11T11:34:06+02:00",
"birthdate": "1991-05-13T08:02:32+02:00",
"deletedAt": null,
"town": "Miami"
},
{
"user": "/api/users/3",
"id": 2,
"gender": "MALE",
"createdAt": "2019-04-05T13:59:30+02:00",
"updateAt": "2019-04-11T10:57:40+02:00",
"birthdate": "1999-04-05T11:48:46+02:00",
"deletedAt": null,
"town": "New York"
},
{
"user": "/api/users/7",
"id": 3,
"gender": "MALE",
"createdAt": "2019-04-11T11:11:03+02:00",
"updateAt": "2019-04-11T11:11:03+02:00",
"birthdate": "1991-05-13T08:02:32+02:00",
"deletedAt": null,
"town": "New York"
}
]
When I add the next code for ORDER BY disntace (calculated between coordinates of user and the point)
$queryBuilder
->addSelect("ST_Distance(o.point, ST_Point(:longitude,:latitude)) AS distance")
->addOrderBy("distance", "ASC")
->setParameter("longitude", $longitude)
->setParameter("latitude", $latitude)
;
I get:
[
{
"0": {
"user": "/api/users/1",
"id": 1,
"gender": "MALE",
"createdAt": "2019-04-05T11:03:03+02:00",
"updateAt": "2019-04-11T11:34:06+02:00",
"birthdate": "1991-05-13T08:02:32+02:00",
"deletedAt": null,
"town": "Miami"
},
"distance": "106496.35623204"
},
{
"0": {
"user": "/api/users/7",
"id": 3,
"gender": "MALE",
"createdAt": "2019-04-11T11:11:03+02:00",
"updateAt": "2019-04-11T11:11:03+02:00",
"birthdate": "1991-05-13T08:02:32+02:00",
"deletedAt": null,
"town": "New York"
},
"distance": "109073.2944295"
},
{
"0": {
"user": "/api/users/3",
"id": 2,
"gender": "MALE",
"createdAt": "2019-04-05T13:59:30+02:00",
"updateAt": "2019-04-11T10:57:40+02:00",
"birthdate": "1999-04-05T11:48:46+02:00",
"deletedAt": null,
"town": "New York"
},
"distance": "285892.32591062"
}
]
I need to the result seem like the 1st json. It is possible to add ORDER BY but remove/hide the distance property?
As of doctrine 2.2, Scalar mappings can now be omitted from DQL result,
using the HIDDEN keyword, so to omit the computed field from the result:
->addSelect("ST_Distance(o.point, ST_Point(:longitude,:latitude)) AS HIDDEN distance")
DQL select expressions documentation
DQL examples

How to get list of Users under a certain Manager/Approver in Coupa API?

I'm lost and I'm hoping that someone may have worked on this before.
So Coupa has its API:
https://coupadocs.atlassian.net/wiki/display/integrate/Users+API
I was able to retrieve user information together with the corresponding manager. Sample response:
https://unknownserver-test.coupahost.com/api/users?employee-number=10003323
[
{
"id": 2756,
"created-at": "2017-03-30T09:29:19-05:00",
"updated-at": "2017-03-31T04:30:53-05:00",
"login": "user1.user1",
"email": "staging23#coupa.com",
"purchasing-user": false,
"expense-user": false,
"sourcing-user": false,
"inventory-user": false,
"employee-number": "10003323",
"phone-work": null,
"phone-mobile": null,
"firstname": "user1",
"lastname": "user1",
"fullname": "user1 user1",
"api-user": false,
"active": false,
"salesforce-id": null,
"account-security-type": 0,
"authentication-method": "coupa_credentials",
"sso-identifier": null,
"default-locale": null,
"default-account": null,
"business-group-security-type": null,
"edit-invoice-on-quick-entry": false,
"avatar-thumb-url": null,
"mention-name": "user1user1",
"company-employee-id": "10003323",
"netsuite-employee-id": "10003323",
"subsidiary": {
"id": 1592,
"external-ref-num": null,
"external-ref-code": "company North America:1"
},
"job-title": {
"id": 2591,
"external-ref-num": null,
"external-ref-code": "VP, Sales"
},
"employee-type": "",
"default-expense-region": "",
"default-geo-spend": "",
"notes": "",
"exclude-from-autosarf": "",
"roles": [
{
"id": 10,
"name": "Expense User"
}
],
"manager": {
"id": 838,
"login": "john.doe",
"email": "staging#coupa.com"
},
"default-currency": {
"id": 1,
"code": "USD"
},
"department": {
"id": 342,
"name": "Sales - Exec:176"
},
"expenses-delegated-to": [],
"can-expense-for": [],
"content-groups": [],
"account-groups": [],
"approval-groups": [],
"working-warehouses": [],
"inventory-organizations": [],
"created-by": {
"id": 2748,
"login": "user1 creator",
"email": "user1.creator#company.com"
},
"updated-by": {
"id": 2748,
"login": "user1 creator",
"email": "user1.creator#company.com"
}
}
]
What I've tried are these:
https://unknownserver-test.coupahost.com/api/users?user[manager][id]=838&return_object=shallow
https://unknownserver-test.coupahost.com/api/users?manager[id]=838&return_object=shallow
https://unknownserver-test.coupahost.com/api/users?users[user][manager][id]=838&return_object=shallow
https://{{URL PREFIX}}.{{HOST}}.com/api/users?manager_id=838&return_object=shallow
If you only need the IDs of the users, you'd get better performance with return_object=limited
If there are more than 50 users returned, you'll have to paginate with the offset query param.

rivers with elastic search with relational data

Consider the following sql schema:
Where Table_2 and Table_1 have a many to many relation
now I'm trying to create an elastic search river that will pull in all the data from table_2 but I want the rows from table_1 as well and not just the id's.
Here is what I believe will be my sql:
select t2.*, t1.Name from [Table_2] t2
join [Table_3] t3 on t2.ID = t3.table_2
join [Table_1] t1 on t1.ID = t3.table_1
Now after doing this I have noticed that I get duplicate rows IE for each relationship in Table_3 I will get one row, I understand why this is but what I want is one entry for Table_2 that has an entry for table one.
This is what I'm getting in elastic now
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "test_relation",
"_type": "relation",
"_id": "AUpUGlvaRCP4Gzd2p3K4",
"_score": 1,
"_source": {
"Name": [
"table_2test",
"Test1"
],
"ID": 1
}
},
{
"_index": "test_relation",
"_type": "relation",
"_id": "AUpUGlvaRCP4Gzd2p3K5",
"_score": 1,
"_source": {
"Name": [
"table_2test",
"Test2"
],
"ID": 1
}
}
]
}
}
But instead I want it to look like:
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "test_relation",
"_type": "relation",
"_id": "AUpUGlvaRCP4Gzd2p3K4",
"_score": 1,
"_source": {
"Name": [
"table_2test",
],
Table_1 :[
{"Name": "Test1", "ID": "1"},
{"Name": "Test2", "ID": "2"}
]
"ID": 1
}
}
]
}
}
I was hoping to get away with using an elasticsearch river for sql but I'm not sure if it allows for this kind of query.