Laravel - How to combine multiple queries as one Eloquent Query - laravel

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();

Related

facing difficulty on implementing "groupBy" method in laravel

I am trying to fetch data using groupBy method in laravel, but it's returning all data. what I am trying to get is
lets there are 2 tables
Table 1 : variants
id variant
1 color
2 size
Table 2: product_variants
color variant_id
red 1
yellow 1
red 1
sm 2
xl 2
lg 2
Now I want to fetch data so it returns as follow:
variant_table: {
id:1,
variant: color,
variants: {
variant_id: 1,
color:red
},
{
variant_id: 1,
color:yellow
}
},
{
id:2,
variant: size,
variants: {
variant_id: 2,
color:sm
},
{
variant_id: 2,
color:lg
},
{
variant_id: 2,
color:xl
}
}
But I am getting all variants instead of distincts grouped by variant_table id, My code:
$productVariants = ProductVariant::with('productVariants')
->whereHas('productVariants',function ($q) {
$q->groupBy('variant_id');
})
->get();
let suppose the model of product_variants table is ProductVariant
let suppose the model of variants table is Variant
let suppose the in model ProductVariant the relation function name is variant()
$product_variants = ProductVariant::with('variant')->groupBy('variant_id')->get();
try this $product_variants = ProductVariant::with('variant')->get()->groupBy('variant_id');
if it does not work than config\database.php --> "mysql" array
Set 'strict' => false

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();

Alter child collections of two models in Laravel

I have this:
$merge = parents::with('children')->get();
which gives me:
[{
"id":1,
"parent_name":"Robert",
"children":[{
"id":5,"name":"Susan","dob":"2010-11-11"},
{"id":7,"name":"Tony","dob":"2014-12-10"}]
}]
I want to add age into children with expected output like this:
[{
"id":1,
"parent_name":"Robert",
"children":[{
"id":5,"name":"Susan","dob":"2010-11-11","age":"10"},
{"id":7,"name":"Tony","dob":"2014-12-10","age":"7"}]
}]
I tried this:
return $merge->map(function ($detail) {
$detail->age = \Carbon\Carbon::parse($detail->dob)->diffInYears();
return $detail;});
it gives me:
[{
"id":1,
"parent_name":"Robert",
"age":0,
"children":[{
"id":5,"name":"Susan","dob":"2010-11-11"},
{"id":7,"name":"Tony","dob":"2014-12-10"}]
}]
I tried:
return $merge->children->map(function ($detail) {
$detail->age = \Carbon\Carbon::parse($detail->dob)->diffInYears();
return $detail;});
It returns
Property [children] does not exist on this collection instance.
Is there any simple way to achieve my goal?
loop on each parent and its children and add new age property
$data = parents::with('children')->get();
$data->each(function($parent) {
$parent->children->each(function($child){
$child->age = \Carbon\Carbon::parse($child->dob)->diffInYears();
});
});
what I suggest and I think is better is to add an attribute to your Model like so:
class modelName extends Model{
protected $append = ['age'];
public function getAgeAttribute(){
return \Carbon\Carbon::parse($this->dob)->diffInYears();
}
}
Loop through parents and its children. Eventually calculate the age and put the value to array.
$merge->map(function ($mer) {
$mer->children->map(function ($child) {
$age = \Carbon\Carbon::parse($child->dob)->diffInYears();
$child->age = $age;
});
});

How to query without using Eloquent?

I have these few tables:
issues
1. id
2. name
tags
1. id
2. name
issue_tag
1. issue_id
2. tag_id
images
1. id
2. url
3. issue_id
The relationship of these tables is stated below:
Issue hasMany Images, Images belongsTo Issue
Issues belongsToMany Tags, Tags belongsToMany Issues
How can I retrieve all the records by NOT USING ELOQUENT, just by using the QUERY BUILDER. I would like to retrieve the data in the format like:
[
{
id: issue_id,
name: issue_name,
tags: [
{
id: tag_id_1,
name: tag_name_1
},
{
id: tag_id_2,
name: tag_name_2
}
]
},
{
...
},
...
]
Please someone help me because I could not solve this problem for a long time, I can only solve it by using Eloquent. But using Eloquent is not a solution for me.
You can use join query. For Details follow this link demo
Or
Use DB:: statement ('your raw query here'). Hope this helps.
Use can Laravel DB::select(); function
With the use of select, we can pass Raw SQL query into select
$innerData = [];
$issueAll = DB::select('select i.id,i.name,i2.url as image,t.id as tag_id,
t.name as tag_name,it.issue_id from issues as i
inner join issue_tag as it on it.issue_id=i.id
inner join tags as t on it.tag_id = t.id
inner join images as i2 on i.id = i2.issue_id
');
foreach ($issueAll as $issue) {
$innerData[$issue->id]["id"] = $issue->id;
$innerData[$issue->id]["name"] = $issue->name;
if (isset($innerData[$issue->id]['tags'][$issue->issue_id])) {
array_push($innerData[$issue->id]['tags'], ['id'=>$issue->tag_id, 'name'=>$issue->tag_name]);
} else {
$innerData[$issue->id]['tags'][$issue->issue_id] = ['id'=>$issue->tag_id, 'name'=>$issue->tag_name];
}
}
return $innerData;
The response you get
{
"1":{
"id":1,
"name":"issue1",
"tags":{
"1":{
"id":1,
"name":"tag1"
},
"2":{
"id":1,
"name":"tag1"
}
}
},
"2":{
"id":2,
"name":"issue2",
"tags":{
"2":{
"id":1,
"name":"tag1"
}
}
}
}
Hope it helps.
In laravel if you don't want to use eloquent then you can use with DB::statement('your query') and don't forget to use USE DB; at the top of the file

Laravel query result, change the column name into numeric

I just wonder how to convert the key of query result into numeric. This is my query result for the example:
$result = [{
"lat": "43289043208",
"lng": "-3890423802"
},...]
What I want is
$result = [{
0: "43289043208",
1: "-3890423802"
},...]
Any helps would be appreciated.
You can use array_values() method.
And iterate the result array
$newArray = [];
foreach(json_decode($result) as $res)
{
$newArray[] = array_values($res);
}
Finally, I use this, and it solved for now
$table_data = DB::table($table)->select(DB::raw("$lat_field as '0'"), DB::raw("$lng_field as '1'"))->get();

Resources