How to Query if Multiple Columns Reference to the Same Table - sql

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;

Related

Laravel 7 Eloquent models - (not being able to do where outside table) Unable to find column on businessDeveloper.user_id, select * from opportunities

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'businessDeveloper.user_id' in 'where clause' (SQL: select * from opportunities where businessDeveloper.user_id = 3)
Hello, I'm using Laravel 7 and eloquent models for a school project. We were told not to use joins and besides making a custom JSON string with the formatted data which will take a lot of work since I have the same problem for other functionalities as well. I got no clue how to solve my problem. The tables are like this:
Opportunities(business_developer_id FK) belongTo-> businessDevelopers(user_id FK) belongTo-> user
So I try to show all opportunities for a logged in business developer. But this doesn't seem to work:
public function qryOpportunities()
{
$opportunities = Opportunity::where('businessDeveloper.user_id', Auth::id())->with('businessDeveloper.user', 'consultantOpportunity.consultant.user', 'contactPerson', 'customer', 'headOfDepartment.user')->get();
return $opportunities;
}
A solution to show all opportunities from the logged-in business developer is much appreciated. Thanks in advance.
Try ->whereHas() :
public function qryOpportunities()
{
$opportunities = Opportunity::whereHas('businessDeveloper', function($q) {
$q->where('user_id', Auth::id());
})
->with('businessDeveloper.user', 'consultantOpportunity.consultant.user', 'contactPerson', 'customer', 'headOfDepartment.user')
->get();
return $opportunities;
}
You can check the docs of whereHas() here: https://laravel.com/docs/7.x/eloquent-relationships#querying-relationship-existence
I suggest you use this code:
public function qryOpportunities()
{
return Opportunity::query()
->whereHas('businessDeveloper', function($query) {
$query->where('user_id', Auth::id());
})->with('businessDeveloper.user', 'consultantOpportunity.consultant.user', 'contactPerson', 'customer', 'headOfDepartment.user')
->get();
}

Covert SQL to Laravel Query Builder

I'm a beginner regarding Laravel Query Builder, can you guys help me convert this SQL to Query Builder
public function check_available_room(Request $request, $checkin_date)
{
$available_rooms = DB::SELECT("SELECT * FROM rooms WHERE id NOT IN (SELECT room_id FROM bookings WHERE '$checkin_date' BETWEEN checkin_date AND checkout_date)");
}
Book model
function rooms() {
return $this->belongsTo(Room::class, 'room_id');
}
Room model
public function bookings() {
return $this->hasMany(Booking::class);
}
Thank you so much
Here is a solution if you have your models and relations in place
$availableRooms = Room::whereDoesntHave('bookings', function($bookingQuery) use ($checkin_date) {
$bookingQuery->where('checkin_date', '<', $checkin_date)
->where('checkout_date', '>=', $checkin_date);
})->get();
$unavailable_room_ids = Booking::where('checkin_date', '<', $checkin_date)
->where('checkout_date', '>=', $checkin_date)
->pluck('room_id')->get();
$available_rooms = Room::whereNotIn('id', $unavailable_room_ids)->get();

how to make a subquery using the query builder of laravel

I want to do the following mysql query with the query builder of Laravel 7:
SELECT r.id, (SELECT date FROM posts as pp where r.id = pp.request_id
ORDER BY STR_TO_DATE(SUBSTRING(pp.date, 1, 19),'%Y-%m-%dT%H:%i:%s') DESC limit 1), r.delivery_mode FROM requests AS r
LEFT JOIN posts AS p ON r.id = p.request_id
group by r.id;
However unfortunately I don't understand how to obtain the latests post date for every request using the query builder of Laravel. I suppose I should do a subquery as in the query above. This is my code:
$query = DB::table('requests');
$query->select(DB::raw('DISTINCT(requests.id)'),'requests.delivery_mode',DB::raw('posts.date'));
$query->leftJoin('posts', 'requests.id', '=', 'posts.request_id');
$requests_list = $query->get();
In the table posts, the date is a string in this format: 2020-04-16T12:46:33+02:00. So I used that complicated functions because I want to see only the latest date post grouped by id_request, that is the foreign key of the table posts connected with the primary key id of the table requests. A request can have many posts.
Can help?
PS:
I found the solution:
$query = DB::table('requests');
$query->select(DB::raw('DISTINCT(requests.id)'),'requests.delivery_mode',DB::raw("(SELECT date FROM posts as pp where requests.id = pp.request_id ORDER BY STR_TO_DATE(SUBSTRING(pp.date, 1, 19),'%Y-%m-%dT%H:%i:%s') DESC limit 1) as lastPostDate"));
$query->leftJoin('posts', 'requests.id', '=', 'posts.request_id');
$requests_list = $query->get();
Probably it isn't a pretty solution but it works!.
Request Model
public function posts()
{
return $this->hasMany(Post::class);
}
Post Model
public function request()
{
return $this->belongsTo(Request::class);
}
Controller
public function index()
{
$date = Post::has("request")
->orderBy(...) // add your order by condition here
->limit(1)
->pluck("date");
$requests = Request::with("posts")
->where("date", $date)
->get();
return $requests;
}

Select specific columns of table and relation in laravel

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

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