I want to fetch data from three tables. the table is named as Student admission and course. In my query, I fetch student data and admission data using the below query
$student = Student::with('student_fees')->with('admissions')->get();
and I also want course table data, but the course table data are related to admission table. how can I fetch course table data using this query?
$users = DB::table('Student')->join('admissions', 'student.id', '=', 'admissions.student_id')->join('course', 'course.id', '=', 'admissions.course_id')->select('Student.*', 'Student.name', 'course.name')->get();
https://laravel.com/docs/5.7/queries#joins - this could help you
You can use nested eager loading
https://laravel.com/docs/8.x/eloquent-relationships#nested-eager-loading
Assume that you defined the relation with the Laravel convention in each Model Class. You can call the nested eager loading like following:
$student = Student::with(['student_fees', 'admissions', 'admissions.course'])->get();
Related
How do I apply join for this kind of table where document_id is stored in array. I am aware about explode function but I really dont know how to use. I do not want to use for loop but I am expecting better idea to join this table. If I have to add something then I will add.
$row = DB::table('service_documents')->select('service_documents.document_id', 'service_documents.service_id')->get();
$idArr = explode(',', $row);
dd($idArr);
$documents = DB::table('service_documents')->select('service.name_np as serviceName',
'documents.name_np as documentName', 'service_documents.*')
->join('service', 'service_documents.service_id', '=', 'service.id')
->join('documents', 'service_documents.document_id', '=', 'documents.id')
->get();
This is my join query in laravel
The best solution (to have a performant query) is to add a new pivot table document_service_document with service_document_id and document_id as fields.
Then populate that table using existing document_id field and adapt all the codes linked to that field to use the pivot table instead.
for that, and after, you can use manyToMany relation or simple join and get the results you need the easy way.
I'm trying to make a query to get my data base on Dispenser's state_id. so here's my Database :
Dispenser Table: id, state_id, town_id, name.
Marketer Table: id, state_id, town_id, fname, lname.
DistributorDispenser Table: distributor_id['foreign key to distributor table', which it doesn't matter for this example], dispenser_id['foreign key to dispenser id'].
Consider below query which i was using for my spa which it's vue.js & laravel, now i want to change this query to check dispenser state_id then get detail base on user state_id.
I mean when we use relation to get some data base on relationship, like ->detail(function name in Model), i want my query to execute where query with DistributorDispenser->dispenser->state_id for my auth()->user()->detail()->state_id.
return SellerCentralResources::collection(DistributorDispenser::where('state_id', auth()->user()->detail->state_id)
->latest()
->get());
You need to use
https://laravel.com/docs/5.8/eloquent-relationships#querying-relationship-existence
DistributorDispenser::query()
->whereHas('dispenser',function($q){
$q->where('state_id', auth()->user()->detail->state_id);
})
->latest()
->get();
I have a model User that has many Orders. Orders have many products, with the pivot table order-product. I don't want to preload and iterate through the orders if at all possible.
I need to return users where
signed_date === true on User
order_date on Order is after signed_date on User
order-product shows product hasn't been paid
I am failing on number 2.
In the following code, the first query within whereHas is wrong. I don't know how to reference the signed date of the user from within the where has. If I was iterating through users in a collection I could do something like ($query) use $user, but how do I do this without preloading all the users?
return User::whereNotNull('signed_date')
->whereHas('orders', function ($query) {
$query->where('order_date', '<=', 'user.signed_date');
$query->whereHas('products', function ($q) {
$q->where('paid', false);
});
})
->get(['id','fname','lname', 'title', 'signed_date']);
I would like to use eloquent if possible. If that is not possible, I would be happy for tips in solving this problem using the query builder/sql.
The Eloquent query builder has a special function called whereColumn('a', '<=', 'b') to compare columns instead of a column against a value. Using this function instead of a normal where() is necessary because of the way the query builder builds the actual query. You need to let the query builder know that you are going to pass a column name instead of a value for proper escaping and formatting of the query string.
Anyway, it seems you can also pass column names prefixed with a table name to the function, allowing you to compare columns across tables:
$query->whereColumn('orders.order_date', '<=', 'users.signed_date')
This works because you are using whereHas() in your query. Your query basically gets translated to:
SELECT id, fname, lname, title, signed_date
FROM users
WHERE signed_date NOT NULL
AND EXISTS (
SELECT 1
FROM orders
WHERE orders.order_date <= users.signed_date
AND EXISTS (
SELECT 1
FROM products
WHERE paid = 0
)
)
It might actually be not necessary at all to use the table name together with the column name in whereColumn(). But in case you'll ever add a column named the same on another table, the query might break - so IMHO it is good practice to use the table name in custom queries.
By the way, the reason this will not work together with with('relationship') is that this function results in an additional query and you obviously cannot compare columns across queries. Imagine the following:
Order::with('user')->take(5)->get();
It will be translated into the following:
SELECT *
FROM orders
LIMIT 5
SELECT *
FROM users
WHERE id IN (?, ?, ?, ?, ?)
where the five ? will be the user_ids of the orders. If the first query returns multiple rows with the same user_id, the amount of rows fetched from the users table gets reduced of course.
Note: All the queries are only examples. Might be that the query builder builds different queries based on the database type and/or escapes them differently (i.e. column names in backticks).
I have two tables :
users table
{id, name}
payments table
{id, user_id, payment}
Here I want to join two tables and want to use SUM(payment) function group by id.
please give me a solution.
You can do join like this way:
$payments = DB::table('users')->join('payments','users.id','=','payments.user_id')->groupBy('users.id')->sum('payment');
//use DB to in you controller
You can use a queryBuilder for make de custom query.
Following is my query
$user = User::select(['uuid','name','about'])->with(['education','work'])->first();
this returns empty data for relationship education and work,
but if I remove select function from query I am getting data in relationship and it also returns all columns of user table which I don't want.
how can solve this problem
The problem is that relationships (with(...)) execute an additional query to get the related results. Let's say you have one to many relationship where users have many works. User::with('work')->find(1) will then execute these 2 queries:
select user where id = 1 and select works where user_id = 1.
So basically in order to be able to execute the second query (fetch relationship data) you need to include id (or whichever column you're referencing) in you select statement.
Fix:
$user = User::select(['uuid','name','about', 'id'])->with(['education','work'])->first();
Same principle in different forms applies to all relationships. For example in the inverse of hasMany which is belongsTo you would need to select the foreign key (for example user_id).