Laravel collection nested group by get different field count - laravel

There is data as below.
"2017-08-13": [
{
"cancelledByDriver": 0,
"busy": 0,
"cancelledByRider": 0,
"acceptedByDriver": 1,
"requestDate": "2017-08-12T21:03:29.754Z"
},
{
"cancelledByDriver": 0,
"busy": 0,
"cancelledByRider": 0,
"acceptedByDriver": 1,
"requestDate": "2017-08-12T21:08:28.244Z"
}
],
"2017-08-14": [],
"2017-08-15": [],
"2017-08-18": [],
"2017-08-20": [],
"2017-08-21": [],
"2017-08-22": [],
"2017-08-23": [],
"2017-08-24": [],
"2017-08-25": []
I want to print the number of values in fields 1 in each date.So in a date how many cancelledByDriver, busy, canceledByRider and acceptedByDriver (value = 1).
Example:
"2017-08-13": [
{
"cancelledByDriver": 0,
"busy": 0,
"cancelledByRider": 0,
"acceptedByDriver": 2,
}
]
My Code:
$days = $tripRequests->groupBy(function($item) {
return date('Y-m-d', strtotime($item['requestDate']));
})->map(function ($item, $key) {
return collect($item);
});

I'm not sure if you solved the question or not. But I have same question about this. Finally I found answer according to Laravel's Collection guides.
$days = $tripRequests->groupBy(function($item) {
return date('Y-m-d', strtotime($item['requestDate']));
})->map(function ($item) {
return $item->sum('cancelledByDriver') ;
});
First, the method groupBy() is able to group a collection by given keys, that's what you are correctly doing. Then with the method map() allows you to re-mapping the collection objects by walking through the each items which associated with date, such as 2017-08-13. What you need to do is call sum() in order to sum the cancelledByDriver up.
You will get a new collection with the sum of cancelledByDriver which group by-ed by the date.
https://laravel.com/docs/5.6/collections#method-sum

Related

Laravel - Assert json array ids using wildcard

In my application I have a response like this:
{
"items": [
{
"id": 10,
"field": "foo"
},
{
"id": 20,
"field": "bar"
}
]
}
I need to test the content of items and validate each id.
I've tried many solutions but no one works, for example (this is just a kind of pseudo-code):
assertJson(fn (AssertableJson $json) =>
$json->where('items.*.id', [10, 20])
)
Is there a way to use a wildcard to pick every ID and validate using an array?
You can use array_filter:
$idArray = [10, 20];
$myObj = json_decode($json); // Turn JSON to obj
$items = $myObj["items"]; // Get items from object
// Filter the items for items that aren't in the ID list
$invalidItems = array_filter($items, function ($el) {
// If the item has an id which isn't in the array, return true
return !in_array($el["id"], $idArray);
});
// This returns true if we found 0 items with IDs not in the ID list
return $invalidItems == [];
You can similarly use array_map to simplify your array, then compare it to your ID array:
$myObj = json_decode($json); // Turn JSON to obj
$items = $myObj["items"]; // Get items from object
$outIdArray = array_map(function($el) {
return $el["id"];
}, $items);
// Compare $outIdArray to [10, 20]
Not tested yet but below should work.
We attach an each on each child element under items and add a callback to where on that id key of each child.
<?php
assertJson(fn (AssertableJson $json) =>
$json->each('items', fn (AssertableJson $childJson) =>
$childJson->where('id', fn($idVal) =>
in_array($idVal, [10,20])
)
)
)

How we get specific columns from multiple relations using With() in Laravel

I need some specific columns from two relations.
In my questions model I have two relations
public function ans_options()
{
return $this->hasMany('App\Models\AnswerChoices', 'ac_quest_id', 'q_id');
}
public function question_category()
{
return $this->hasOne("App\Models\Categories", 'cat_id', 'q_category');
}
I tried
Questions::with(array(
'questionCategory' => function($query) {$query->select('cat_id','cat_value');},
'ans_options' => function($query1) {$query1->select('ac_id','ac_choiceTxt');}
))->get();
am getting only the columns of question_category not in ans_options
{
"q_id": 349,
"q_project_id": 140,
"q_text": "<p>Gender</p>",
"question_category": {
"cat_id": 1,
"cat_value": "normal"
},
"ans_options": []
}
But when I try the below code all columns of ans_options are getting.
Questions::with('questionCategory:cat_id,cat_value','ans_options')->get();
like
{
"q_id": 349,
"q_project_id": 140,
"q_text": "<p>Gender</p>",
"question_category": {
"cat_id": 1,
"cat_value": "normal"
},
"ans_options": [
{
"ac_id": 334,
"ac_quest_id": 349,
"ac_choiceTxt": "Male",
"ac_modifiedOn": "2021-11-24T06:22:00.000000Z",
"ac_status": "active"
},
{
"ac_id": 335,
"ac_quest_id": 349,
"ac_choiceTxt": "Female",
"ac_modifiedOn": "2021-11-24T06:22:00.000000Z",
"ac_status": "active"
}
]
}
I need only ac_id and ac_choiceTxt from ans_options. How can I achieve that?
to make Laravel able to load the relation, you should select the foreign key that responsible for that relation
Questions::with(array(
'questionCategory' => function ($query) {
$query->select('cat_id', 'cat_value');
},
'ans_options' => function ($query1) {
$query1->select(
'ac_id',
'ac_choiceTxt',
'ac_quest_id'
);
}
))->get();
just add 'ac_quest_id' to your select.
You can make model where available only this fields
Extend current model from new (with removing columns from curent)
use "with" from new short model
I don't know another way at now...
Then we can add the primary key here also. It will get the same result and then no need of closures here.
Questions::with('questionCategory:cat_id,cat_value',
'ans_options:ac_id,ac_choiceTxt,ac_quest_id')
->get();

Laravel - How to combine multiple queries as one Eloquent Query

In my Laravel-5.8, I have these four queries accessng the same model:
$allLeaves = HrLeaveRequest::where('company_id', $userCompany)->whereYear('created_at', date('Y'))->count();
$pendingLeaves = HrLeaveRequest::where('leave_status', 1)->where('company_id', $userCompany)->whereYear('created_at', date('Y'))->count();
$rejectedLeaves = HrLeaveRequest::where('leave_status', 3)->where('company_id', $userCompany)->whereYear('created_at', date('Y'))->count();
$approvedLeaves = HrLeaveRequest::where('leave_status', 4)->where('company_id', $userCompany)->whereYear('created_at', date('Y'))->count();
How do I combine the four queries as one
something similar to this
$gender_unpublished_record = HrEmployee::selectRaw('count(gender_code) as count,gender_code, if (gender_code = 1, "Male", "Female") as gender')->whereNotIn('employee_code', $publishedgoals)->where('company_id', $userCompany)->where('hr_status', 0)->groupBy('gender_code')->get();
The one above only have 0 or 1. But what I want to achive takes care of everything in the table, leave_status as 1, 3 and 4
Thank you
in your Company Model you should have the relation:
public function HrLeaveRequests()
{
return $this->hasMany(HrLeaveRequest::class,'company_id');
}
now you could use withCount:
$value=Company::where('company_id',$userCompany)->withCount(['HrLeaveRequests as allLeaves'=>function($query){
$query ->whereYear('created_at', date('Y'));
},
'HrLeaveRequests as pendingLeaves'=>function($query){
$query->where('leave_status', 1)->whereYear('created_at', date('Y'));
},
'HrLeaveRequests as rejectedLeaves'=>function($query){
$query->where('leave_status', 3)->whereYear('created_at', date('Y'));
},
'HrLeaveRequests as approvedLeaves'=>function($query){
$query->where('leave_status', 4)->whereYear('created_at', date('Y'));
},
])->get();

How to make a condition based on relation ship count in Laravel Eloquent?

I would like to add a condition based on the tasks relationship count,
Here is the code:
return TeamleaderDeal
::withCount('tasks')
->get();
The result is:
[
{
"id": 4,
(...)
"dealPhase": "Refused",
"tasksCount": 5,
(...)
},
{
"id": 5,
(...)
"tasksCount": 0,
"companyLanguage": "nl",
(...)
},
{
"id": 16,
(...)
"dealPhase": "New",
"tasksCount": 17,
(...)
},
{
(...)
How to only return results where tasksCount equal to 5?
You may use has method like this:
// Retrieve all team-leader deals that have 5 tasks...
return TeamleaderDeal
::has('tasks', '=', 5)
->get();
Check Laravel docs for more info.

Conditional update of several fields

I'm new with rethinkdb, I'm trying to write an update query preferred upsert which will set values to several fields if they don't exist or their values is less than the new value I want to set. Below is the way I did it with mongodb
collection.updateOne(new BasicDBObject(BookKeeperEvent.tenantPropertyName, bookKeeper.getTenantId()).append(BookKeeperEvent.timeLayerPropertyName, bookKeeper.getTimeLayer()),
new BasicDBObject("$max", new BasicDBObject(BookKeeperEvent.latestFullDataPropertyName, bookKeeper.getLatestFullData())
.append(BookKeeperEvent.latestRawDataPropertyName, bookKeeper.getLatestRawData())
.append(BookKeeperEvent.latestHealthPropertyName, bookKeeper.getLatestHealth())
.append(BookKeeperEvent.lastUpdatePropertyName, bookKeeper.getLastUpdate())
.append(BookKeeperEvent.firstFullDataPropertyName, bookKeeper.getFirstFullData()))
.append("$setOnInsert", new BasicDBObject(BookKeeperEvent.tenantPropertyName, bookKeeper.getTenantId()).append(BookKeeperEvent.timeLayerPropertyName, bookKeeper.getTimeLayer())),
new UpdateOptions().upsert(true))
This code set tenantId and timeLayer only if they are null, and for the other fields only if they are null or the value is less than the value I set in the query.
Is there a way to do the same thing in rethinkdb? and how?
I think the following query is equivalent to what I did in mongo but it fails.
r.table('book_keeper').filter({tenantId: '123', timeLayer: 4}).coerceTo('array').do(function (matches) {
return r.branch(
matches.isEmpty(),
r.table('book_keeper').insert({tenantId: '123', timeLayer: 4, latestRawData: 100, id: 4}),
r.table('book_keeper').get(4).update(function (doc) {
return r.branch(
doc.not(doc.hasFields('firstFullData')).or(doc('firstFullData').lt(100)),
{firstFullData : 100},
null)
}
))
})
The excption is:
e: Expected 1 argument but found 2 in:
r.table("book_keeper").filter({"tenantId": "123", "timeLayer": 4}).coerceTo("array").do(function(var_193) { return r.branch(var_193.isEmpty(), r.table("book_keeper").insert({"tenantId": "123", "timeLayer": 4, "latestRawData": 100, "id": 4}), r.table("book_keeper").get(4).update(function(var_194) { return r.branch(var_194.not(var_194.hasFields("firstFullData")).or(var_194("firstFullData").lt(100)), {"firstFullData": 100}, null); })); })
How can I fix it?
Thanks,
Daniela

Resources