Laravel - Select only specified columns in joined tables - php

Here's my situation I have joined tables but the problem is some of those columns have the same name from other tables. What I want to know is how I can prevent this from happening. The columns that have the same name are created_at but I only want to use methods' table created_at (methods.created_at). Here is my code to explain my situation better
$filtered_table = Method::leftJoin('users', 'users.id', '=', 'methods.created_by')
->leftJoin('roles', 'roles.id', '=', 'users.role_id')
->leftJoin('types', 'types.id', '=', 'methods.type_id')
->where($request->filters)//will act as a searchmap
->get([ 'users.username', 'users.id AS users_id', 'methods.*', 'methods.id AS method_id', 'methods.name AS method_name', 'roles.id AS role_id', 'roles.name AS role_name',
'types.id AS type_id_typetable', 'types.name AS type_name']);
notice how ->where is an array of objects, I am using it as a searchmap for the clause. But my problem is like what I said above that the tables has the same name on some columns like for example created_at, the other columns doesn't matter since I am not using it.
The question is how do I explicitly tell the query that I am using the methods.created_at when I am searching it through the searchmap (In this case, $request->filters['created_at']. Please, let me know if you need any more details.
EDIT
if($("#date_select_off").val() == "daily") {
let day = $("#day_date").val();
filter_list.created_at = day;
}
in this code in jquery I am naming the key the same as the column so that I can use it as parameter in the php query. But my like my initial problem I simply can't name it filter_list.methods.created_at any help with this is greatly appreciated.
EDIT 2
How would I use a 'LIKE' query to that particular key value pair?
->where($request->filters)//will act as a searchmap
->orWhere('methods.created_at', 'LIKE', $request->filters['methods.created_at'])
I tried doing this but it is just wrong since the key value pair is already hitting on the first where clause.
EDIT 3
It could use some improvements but yeah
$filtered_table = Method::leftJoin('users', 'users.id', '=', 'methods.created_by')
->leftJoin('roles', 'roles.id', '=', 'users.role_id')
->leftJoin('types', 'types.id', '=', 'methods.type_id')
->where($request->filters)//will act as a searchmap
->orWhere('methods.created_at', 'LIKE', '%' . $request->filters['methods.created_at'] . '%')
->get([ 'users.username', 'users.id AS users_id', 'methods.id AS method_id', 'methods.name AS method_name', 'methods.created_at AS method_created_at', 'roles.id AS role_id', 'roles.name AS role_name',
'types.id AS type_id_typetable', 'types.name AS type_name']);

Change your model class as per your requirements to specify what columns you want selected:
public function someModel() {
return $this->belongs_to('otherModel')->select(array('id', 'name'));
}

In this case pass the fully qualified column name in where clause like:
->where('methods.created_at', '=', $request->filters)
or create a table alias and use the alias like:
SELECT col from methods as t1,
...
WHERE t1.col = 'some value';

Related

Laravel Eloquent Join Querying can't access all variables

I have two models defined (Laravel application): AdviceProtocol and Question which you the tables advice_protocols and questions. The models have been linked together by:
public function userGoal() {
return $this->hasOne('App\Question', 'id', 'user_goal_id');
}
I would like to get the following variabels from my query: the advice protocol name, the advice protocol category and questions name. The two tables are linked through a set of ids. The query which I have now is:
public function data(){
$advicePreparationsQuery = AdviceProtocol::select(['advice_protocols.name', 'advice_protocols.category', 'questions.id'])
->join('questions', 'advice_protocols.user_goal_id', '=', 'questions.id')
->get();
The questions.id can be retrieved, but when I change the variable to questions.name: nothing is retrieved. My output doesn't give an error, but no values are returned. Could someone please help me to get the value of questions.name?
name is ambiguous in your query because you're also selecting advice_protocols.name. You need to give one of them an alias so it knows which column is which when you're trying to access $advicePreparationsQuery->name
$advicePreparationsQuery = AdviceProtocol::select(['advice_protocols.name', 'advice_protocols.category', 'questions.name AS question_name'])
->join('questions', 'advice_protocols.user_goal_id', '=', 'questions.id')
->get();
I think the problem is that you are not selecting questions.name...
Try:
$advicePreparationsQuery = AdviceProtocol::select([
'advice_protocols.name', 'advice_protocols.category', 'questions.name'
])
->join('questions', 'advice_protocols.user_goal_id', '=', 'questions.id')
->get();
Try:
$advicePreparationsQuery = AdviceProtocol::select(['advice_protocols.user_goal_id', 'advice_protocols.name', 'advice_protocols.category', 'questions.id', 'questions.name'])
->join('questions', 'advice_protocols.user_goal_id', '=', 'questions.id')
->get();

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.

Laravel Eloquent - Select MAX with other columns

I'm trying to select a number of columns along with MAX. The raw query would be something like: SELECT users.id, ..., MAX(ur.rank) AS rank but I cannot figure out how to do it using the query builder supplied by Laravel in Eloquent.
This is my attempt:
$user = User::join('users_ranks AS ur', function($join) {
$join ->on('ur.uid', '=', 'users.id');
})
->where('users.id', '=', 7)
->groupBy('users.id')
->first(['users.id', 'users.username', 'MAX(ur.rank) AS rank']);
I simply cannot figure it out. What I want to achieve is I'm selecting a user where users.id = 7, and I'm wanting to select the MAX rank that's in users_ranks where their users_ranks.uid = users.id.
I was told to avoid sub-queries as when working with large result sets, it can slow things down dramatically.
Can anyone point me in the right direction? Thanks.
I think you should rewrite it like this:
DB::table('users')
->select(['users.id', 'users.username', DB::raw('MAX(ur.rank) AS rank')])
->leftJoin('users_ranks AS ur', 'ur.uid', '=', 'users.id')
->where('users.id', '=', 7)
->groupBy('users.id')
->first();
No sense to use User:: if you use table names later and want to fetch not all of the fields ( 'users.id', 'users.username' ).

Join tables with equal columns

I have two tables users and cars, the cars has a column owner that is the id of an user and I need to join them. Both users and cars has a column called name and it's overriding. I want to keep both but with different names, like car_name and user_name on the return.
Here is how I'm doing:
$columns = [
DB::raw('cars.name as car_name')
];
$cars = Cars::join('users', 'users.id', '=', 'cars.owner')->get($columns);
It works if I try to print car_name but it still overriding the name and if I print name it still returns the name of the user instead of the car.
Is there a way for doing this right?
You can use the select() clause directly in your query.. no need to use DB::raw():
$cars = Cars::join('users', 'users.id', '=', 'cars.owner')
->select('*','cars.name as car_name')
->get();
The problem with this is that you will end up with a repeated column as you are asking the DB for everything, plus the field with a new name. That may not be a problem for you, but might be better to specify explicitly the fields you want to select:
$cars = Cars::join('users', 'users.id', '=', 'cars.owner')
->select('users.name as user_name','cars.name as car_name', 'whatever_else')
->get();
I don't think you can do what you want with gets - but you can with select. This should hopefully work:
$columns = [
'*',
'users.name as user_name',
'cars.name as car_name'
];
$cars = Cars::join('users', 'users.id', '=', 'cars.owner')->select($columns)->get();

Eloquent - join clause with string value rather than column heading

I have a question regarding join clauses in Eloquent, and whether you can join on a string value rather than a table column.
I have the code below querying a nested set joining parent/child records in a table 'destinations' via a table 'taxonomy'.
The second $join statement in the closure is the one causing an issue; Eloquent assumes this is a column, when I would actually just like to join on t1.parent_type = 'Destination' - ie, t1.parent_type should = a string value, Destination.
$result = DB::connection()
->table('destinations AS d1')
->select(array('d1.title AS level1', 'd2.title AS level2'))
->leftJoin('taxonomy AS t1', function($join) {
$join->on('t1.parent_id', '=', 'd1.id');
$join->on('t1.parent_type', '=', 'Destination');
})
->leftJoin('destinations AS d2', 'd2.id', '=', 't1.child_id')
->where('d1.slug', '=', $slug)
->get();
Is it possible to force Eloquent to do this? I've tried replacing 'Destination' with DB::raw('Destination') but this does not work either.
Thanking you kindly.
Another best way to achieve same is :
$result = DB::connection()
->table('destinations AS d1')
->select(array('d1.title AS level1', 'd2.title AS level2'))
->leftJoin('taxonomy AS t1', function($join) {
$join->on('t1.parent_id', '=', 'd1.id');
$join->where('t1.parent_type', '=', 'Destination');
})
->leftJoin('destinations AS d2', 'd2.id', '=', 't1.child_id')
->where('d1.slug', '=', $slug)
->get();
Replace your on with where
try using DB::raw("'Destination'")

Categories