Select specific columns of table and relation in laravel - sql

Lets consider I have a Model User and another Model Employee
Now I want to pluck only some fields of Employee model such as salary, id, emp_id along with some columns of User model such as name,id.
$employee = Employee::with('user:id,name')
->where('department', $request->department)
->get(['id', 'emp_id', 'salary']);
When I execute this it will return id,emp_id,salary data but for user:name,id it will return null
How can I also specify user:id,name in get() ?

You can either load the full model or only some fields of it. To only load some fields, use select(). It also works within the relationship eager loading query:
$employees = Employee::with(['user' => function ($query) {
$query->select(['id', 'employee_id', 'name']);
}])
->where('department', $request->department)
->select(['id', 'emp_id', 'salary'])
->get();

use select() method from Query bulider:
$employee = Employee::with('user') // or users <---
->select(['id', 'emp_id', 'salary', 'users.id AS user_id', 'users.name AS username'])
->where('department', $request->department)
->get();

Related

Count a Model based on another Model with many-to-many relation

Here's my task:
class Task extends Model
{
public function parts()
{
return $this
->belongsToMany(Part::class)
->withPivot('count');
}
}
Using Eloquent, how I can check how many parts were used for tasks that have end date between X and Y? I want to list all parts at the same time, as there's only several types
By far I got this:
collect(
ProjectTask::with('parts')
->has('parts')
->where('end_date', '>=', $now)
->where('end_date', '<=', $to)
->get()
)
but have no idea what to do next
I'm assumming the following structure
parts
----
id
tasks
----
id
project_task
----
id
part_id
task_id
end_date
count
If that is the case, no relationships are needed.
$count = ProjectTask::query()
->whereBetween('end_date', [$now, $to])
->sum('count');
Or, if you want it grouped:
$grouped_count = ProjectTask::query()
->select('part_id', DB::raw('SUM(count) as count'))
// ->with('part')
->whereBetween('end_date', [$now, $to])
->groupBy('part_id')
->get();
As an aside, doing collect(Model::...->get()) is redundant. The Query Builder's get() method already returns a Collection.

How to Query if Multiple Columns Reference to the Same Table

I am facing an issue here. I have a table called application and it will record who requests the application, who approves it, and who rejects it. The issue is the Requestor_id, Approver_id and Rejector_id are references to the same table. How can I query for the requestor_name, approver_name, and rejector_name in Laravel
Application table
Requestor_id ( reference to user id)
Application_Status
Module_id
Approver_id ( reference to user id)
Rejector_id ( reference to user id)
created_at
updated_at
Below is what I have tried but it can only retrieve for the requestor name
$Approval_Logs = DB::table('application')
->select('application.id','application.Application_Status', 'users.name','application.Approver_id','application.Rejector_id', 'ems_application.Request_Category','application.updated_at')
->join('ems_application', 'ems_application.Application_id', '=', 'application.id')
->join('users', 'users.id', '=', 'application.requestor_id')
->whereIn('application.Application_Status',['approved','rejected'])
->get()
->toArray();
I hope I can receive some hints from you. Thanks in advance!
You may use aliases in your joins also.
$Approval_Logs = DB::table('application')
->select(
'application.id',
'application.Application_Status',
'application.Approver_id',
'approver.name as approver_name',
'application.requestor_id',
'requestor.name as requestor_name',
'application.Rejector_id',
'rejector.name as rejector_name',
'ems_application.Request_Category',
'application.updated_at'
)
->join('ems_application', 'ems_application.Application_id', '=', 'application.id')
->join('users as requestor', 'requestor.id', '=', 'application.requestor_id')
->join('users as approver', 'approver.id', '=', 'application.approver_id')
->join('users as rejector', 'rejector.id', '=', 'application.rejector_id')
->whereIn('application.Application_Status',['approved','rejected'])
->get()
->toArray();
I am not completely familiar with your application, however you may want to utilize left_join instead of join for the approver and rejector joins in the event that there was not an approver or rejector.
If you would like to do it the "Laravel" way. I would create a model called Application and create relations
class Application extends Model {
public function requestor(){
return $this->belongsTo(Users::class, 'requestor_id');
}
public function approver(){
return $this->belongsTo(Users::class, 'approver_id');
}
public function rejector(){
return $this->belongsTo(Users::class, 'rejector_id');
}
}
Then in your controller, you can run the following query:
$application = Application::whereHas('requestor', function($query) {
$query->where('first_name', 'John');
})->whereHas('approver', function($query) {
$query->where('first_name', 'Peter');
})->whereHas('rejector', function($query) {
$query->where('first_name', 'Michael');
})->get();
That should query the users table for the first names. I don't know how efficient this will be, but give it a try;

how to select query tables column with objects in query builder

i am joining two tables with query builder. here is the sample
$events = DB::table('eventcalenders')
->select('eventcalenders.id','eventcalenders.event_name',)
->join('countries', 'eventcalenders.country_id', '=', 'countries.id')->get();
can i declare an object of eventcalender as e and select with object name like 'e.id','e.event_name'.?
Yes, after the query you need to loop through them since they are more than one item:
foreach($events as $e){
$name = $e->event_name;
}
If you want to select only the first one that meets your constrains then use .first().
$event = DB::table('eventcalenders')
->select('eventcalenders.id','eventcalenders.event_name',)
->join('countries', 'eventcalenders.country_id', '=', 'countries.id')->first();
$name = $event->event_name;
$events = DB::table('eventcalenders')
->select('eventcalenders.id','eventcalenders.event_name','countries.*')
->join('countries', 'eventcalenders.country_id', '=', 'countries.id')
->get();
Afetr getting results
foreach($events as $event)
{
echo $event->event_name;
echo $event->country_name; //your specific field
}

whereHas is not working on NULL value

in laravel 5.5 whereHas() is not working on where value is NULL. my relationship with other model is one to many and and i want to pick the values from the model where value is equal to NULL . But instead of returning the specific values its returning all the value in result
plans = Plan::with('objectives')->with('objectives.keyResults')
->whereHas('objectives', function($query) {
$query->whereNull('entity_id');
$query->whereNull('quarter_id');
})->where('companyKey', Auth::user()->companyKey)->get();
You have to specify the constraint twice:
$plans = Plan::with(['objectives' => function($query) {
$query->whereNull('entity_id');
$query->whereNull('quarter_id');
}, 'objectives.keyResults'])
->whereHas('objectives', function($query) {
$query->whereNull('entity_id');
$query->whereNull('quarter_id');
})->where('companyKey', Auth::user()->companyKey)
->get();
No double constraints are needed, simplify it to:
$plans = Plan::whereHas('objectives', function($query) {
$query->whereNull('entity_id');
$query->whereNull('quarter_id');
})->with(['objectives'])
->where('companyKey', Auth::user()->companyKey)
->get();

Laravel 5 - Eloquent Query - Is this possible?

I want to find all of the "Posts" that have users. Users are assigned in groups and I want to find all of the "Posts" that have a particular user group. I can get the posts by name, and that have a usergroup:
$results = Post::PostBySlug("Testing")
->with('groups', 'groups.users')
->first();
This works, but, returns all of the user groups that are assigned to a particular group. I want to do it so that I can select the post, by the slug, and return all the users of a particular group. I have tried:
$results = Post::PostBySlug("Testing")
->with('groups', 'groups.users')
->where('groups.id', '=', 1);
But this did not return anything, only an unknown column. I have tried to do:
$results = Post::PostBySlug("Testing")
->with('groups AS testing', 'groups.users')
->where('testing.id', '=', 1);
But yet, no further. Can anyone suggest where I am going wrong, or suggest an alternative approach to this?
You need a query scope with the given group id.
class Post extends Model {
public function scopeInGroup($query, $group_id) {
return $query->whereHas('groups', function($query) use ($group_id) {
return $query->where('id', $group_id);
}
}
}
Then your query would be:
Post::PostBySlug('Testing')
->InGroup(1)
->with('groups.users')
->get();