Laravel Eloquent - query joint tables contains a same col name - php

I considered an issue when viewing data called from database using two related tables users and roles which have this structure:
the users.role column contains an integer referring to the role record of roles table
the roles.name column contains the role name i.e. (user / admin / editor)
in my controller I used the laravel docs to build my query as I need to show a table in blade that holds users.name , users.email and roles.name that related to user by the schema:
$users = DB::table('users')
->join('roles', 'users.role', '=', 'roles.id')
->select('users.name', 'users.email', 'roles.name')
->get();
actually it works and dumping data, but the issue is the confusion of the two name alike cols users.name and roles.name. it dumping only the roles.name value like this sample record:
{"name":"user","email":"user#asd.com"},{"name":"user","email":"new#asd.com"},{"name":"user","email":"jaeden93#example.org"}
even when I tried to select all cols of users table like below:
$users = DB::table('users')
->join('roles', 'users.role', '=', 'roles.id')
->select('users.*', 'roles.name')
->get();
the users.name col still not showing!
Is there a way to solve this issue without changing table's column titles ?

You can give an alias to the column, to avoid problems with the same name
Use this
$users = DB::table('users')
->join('roles', 'users.role', '=', 'roles.id')
->select('users.*', \DB::raw('roles.name as role_name'))
->get();
It's the same to do this in SQL
SELECT users.*, roles.name as role_name FROM ...

Related

Laravel query join 1 table in 2 tables at single query

I have a complex query and it works, now i need to join users table and get 2 different value of it based on 2 different tables here is where things messed up.
Code
I have commented issue part as well as data that should be returned
$datas = DB::table('projects')
->orderBy('projects.id', 'desc')
->join('customers', 'projects.customer_id', '=', 'customers.id')
->leftjoin('project_schedules', 'projects.id', '=', 'project_schedules.project_id')
->leftjoin('project_schedule_details', 'project_schedules.id', '=', 'project_schedule_details.schedule_id')
->leftjoin('project_schedule_visits', 'projects.id', '=', 'project_schedule_visits.project_id')
// issue tables (project_admins) and (project_shoppers)
->leftjoin('project_admins', 'projects.id', '=', 'project_admins.project_id')
->leftjoin('project_shoppers', 'projects.id', '=', 'project_shoppers.project_id')
->groupBy('projects.id')
->select(
'projects.name as project',
'customers.companyName as customer',
'project_schedule_details.date as schedule_date',
'project_schedule_details.description as schedule_description',
'project_schedule_details.actual_cost as schedule_actual_cost',
'project_schedule_visits.from_date as visit_from_date',
'project_schedule_visits.to_date as visit_to_date',
'project_schedule_visits.description as visit_description'
// 'project_admins.user.username as admin' //i.e. user 1
// 'project_shoppers.user.username as shopper' // i.e user 2
)
->get();
Explanation:
I need to join users table to project_admins table as well as project_shoppers table and return related users to those tables.
Then I would have user 1 returned based on project_admins table
And user 2 based on project_shoppers table.
Any idea how to achieve that goal?
Under the leftJoins you can add the extra joins for getting the users:
->leftJoin('users','users2.id','=','project_admins.user_id')
->leftJoin('users AS users2','users2.id','=','project_shoppers.user_id')
In your select you can get the details like this:
->select(
...,
'users.username AS admin',
'users2.username AS shopper'
)

Inside join make if condition and get details in laravel

I tried to match two columns and if it was matching based on the id i'll assign username to that matched column. but inside join i can't make if condition on joining table.
$list = DB::table('job')
->join('users', 'users.id', '=', 'job.created_by')
->select('job.*','users.first_name as created_by','users.first_name')
->where('job.enterprise_id', $user->id)
->get();
In my json i had one value updated_by with value 1 means i can match with id column if it was matching i will display updated_by = first_name otherwise updated_by = null.
To show the name of user who updated job you can use a left join to users table.
$list = DB::table('job as j')
->join('users as u1', 'u1.id', '=', 'j.created_by')
->leftJoin('users as u2', 'j.updated_by' , '=', 'u2.id')
->select('j.*','u1.first_name as created_by','u2.first_name as updated_by')
->where('j.enterprise_id', $user->id)
->get();
If job was updated u2.first_name will return the name of user who updated that job if job is not update you will have a null value against u2.first_name. Also i assume you job table has a column named as updated_by which stores this information.

Laravel Table Joining

I have three tables .
users
id name
roles
id name
role_user
id user_id role_id
I want to join them like
id name name(role) user_id role_id
My vision is to show the role name of the user.
I have tried this :
DB::table('users')
->join('role_user', 'users.id', '=', 'role_user.user_id')
->join('roles', 'role_user.role_id', '=', 'roles.id')
->select('users.id', 'role_user.role_id', 'roles.name')
->get();
Can you please tell me what I am doing wrong or if I am going thru a bad way.
Thanks in Advance
The name field is "double". This is not a problem for your database but it will not display well. Try the following code:
$result = DB::table('..etc.')->get(['users.*','role_user.role_id','roles.name as role_name']);
foreach($result as $row) {
print_r($row->toArray());
}
As you can see I've changed the get() call to make sure that the user's "name" field does not clash with the role's "name" field.

Laravel Query Returning Null ids on the id column

Okay I have a some code written to retrieve data from some left join in my database, after retrieving this data I use the id from each to populate a modal. The thing is it works for some of the data that has been retrieve. For when i look at the query result I notice the id's are null for some valid data an some or not
$someuser = DB::table('users')
->join('sometable', 'sometable.user_id', '=','users.id')
->leftjoin('sometable', 'users.id', '=', 'skills.user_id')
->leftjoin('sometable', 'users.id', '=','schools.user_id')
->leftjoin('sometable', 'users.id', '=', 'languages.user_id')
->leftjoin('sometable','users.id', '=', 'memberships.user_id')
->leftjoin('sometable', 'users.id', '=', 'convictions.user_id')
->leftjoin('sometable', 'users.id', '=', 'work_experiences.user_id')
->select('users.*','sometable.name as sometablename','sometable.*')
->where('users.first_name', '<>', '')->whereNotNull('users.id')
->orderBy('sometable.updated_at', 'DESC')->groupby('users.first-name')->distinct()->paginate(100);
from that, the query result looks like:
{"total":966,"per_page":100,"current_page":1,"last_page":10,"from":1,"to":100,"data":[{"id":null, etc
What am simple saying why is my id null
I think its not showing me no ids over 1900 so if a user is over 1900 it showing me null
You are selecting * from multiple tables. Since you are also left joining, it's very likely there is nothing to join on so your database is returning those columns as null. Specifically select the id you need and alias it as something which will not be overwritten by another column.

Laravel 5.1: handle joins with same column names

I'm trying to fetch following things from the database:
user name
user avatar_name
user avatar_filetype
complete conversation_messages
with the following query:
static public function getConversation($id)
{
$conversation = DB::table('conversation_messages')
->where('belongsTo', $id)
->join('users', 'conversation_messages.sender', '=', 'users.id')
->join('user_avatars', 'conversation_messages.sender', '=', 'user_avatars.id')
->select('users.name', 'conversation_messages.*', 'user_avatars.name', 'user_avatars.filetype')
->get();
return $conversation;
}
It works fine so far, but the avatar's column name is 'name' like the column name from the 'users' table.
So if I'm using this query the to get the output via $conversation->name, the avatar.name overwrites the users.name
Is there a way to rename the query output like the mysql "as" feature at laravel 5.1?
For example:
$conversation->avatarName
$conversation->userName
Meh okay.. i've found a simple solution here
->select('users.name as userName', 'conversation_messages.*', 'user_avatars.name as avatarName', 'user_avatars.filetype')
As you can mention I've added the requested "as-Feature" next to the table.columnName
Take a look at this example of trying to join three tables staffs, customers and bookings(pivot table).
$bookings = \DB::table('bookings')
->join('staffs', 'staffs.id' , '=', 'bookings.staff_id')
->join('customers', 'customers.id' , '=', 'bookings.customer_id')
->select('bookings.id', 'bookings.start_time', 'bookings.end_time', 'bookings.service', 'staffs.name as Staff-Name', 'customers.name as Customer-Name')
->orderBy('customers.name', 'desc')
->get();
return view('booking.index')
->with('bookings', $bookings);
I had the following problem, simplified example:
$result = Donation::join('user', 'user.id', '=', 'donation.user_id')->where('user.email', 'hello#papabello.com')->first();
$result is a collection of Donation models. BUT CAREFUL:
both tables, have a 'created_at' column. Now which created_at is displayed when doing $result->created_at ? i don't know. It seems that eloquent is doing an implicit select * when doing a join, returning models Donation but with additional attributes. created_at seems random. So what I really wanted, is a return of all Donation models of the user with email hello#papabello.com
solution is this:
$result = Donation::select('donation.*')->join('user', 'user.id', '=', 'donation.user_id')->where('user.email', 'hello#papabello.com')->first();
Yeah, simply rename the column on either table and it should work.
Also what you can do is, rename the user.name column to anything, also rename sender column of conversation_messages to id and perform a natural join.

Categories