laravel ORM relations : using Conditions on With Joins - php

im trying to join two tables post and comment using ORM relations,
$posts = Post::with('comments')->get();
how can i use condition on comments when using with to join tables?
i can use whereHas like
$posts = Post::whereHas('comments', function ($query) {
if(isset($_GET['title']))
$query->where('title', $_GET['title']);
})->get();
but when i use whereHas i wouldn't get the post without any comment in the result
basically i want to use left join with condition on the right table

You can pass a closure to with() method like this:
$posts = Post::with(['comments' => function($q) {
$q->where('column', '=', 'value'); // Put conditions here
}])->get();
Hope this helps!

You need use Closures:
$title = $_GET['title'];
$posts = Post::whereHas('comments', function ($query) use ($title) {
if(!empty($title)) {
$query->where('title', $_GET['title']);
}
})->get();
Reference:
In PHP 5.3.0, what is the function "use" identifier?

Related

filtering the model based on a relationship laravel

So my code is
$categories=Category::where('user_id', $store->id)->whereHas('childrenCategories', function($q) use ($id){
$q->where('user_id', $id);
})->orwhereHas('products', function($q) use ($id) {
$q->where('auth_id', $id);
})->with('products', 'childrenCategories')->latest()->get();
I want to get all children categories with and products with given id but this code doesn't seem to work. As children categories with user_id other than id are also being returned. Sorry, I am relatively new to Laravel. And I thought this would be a good platform to ask. Also, I can share the relationships if you want me to.
I solved this with the following. Thanks, #lagbox for your time.
$categories = Category::with(['childrenCategories' =>
$childrenClosure = function ($query) use ($id) {$query->where('user_id', $id);}, 'products'
=> $productsClosure = function ($query) use ($id) {$query->where('auth_id', $id);}])
->where('user_id', $store->id)
->where(function ($query) use ($childrenClosure, $productsClosure) {$query->whereHas('childrenCategories', $childrenClosure)
->orWhereHas('products', $productsClosure);})
->latest()
->get();

Laravel belongsToMany relation condition

I have created many-to-many relation using belongsToMany function:
class Doctor extends Model
{
...
public function categories()
{
return $this->belongsToMany('App\Category', 'doctors_to_categories', 'doctor_id', 'category_id');
}
...
}
Now I want to create query with many-to-many condition. In SQL in would be:
SELECT *
FROM `doctors`
JOIN `doctors_to_categories`
ON `doctors_to_categories`.`doctor_id` = `doctors`.`id`
WHERE `doctors_to_categories`.`category_id` = 1
I have tried to achieve this like:
$doctors = Doctor::with(['categories' => function($query) {
$query->where('category_id', '=', 1);
}])->get();
Or
$doctors = Doctor::with(['categories' => function($query) {
$query->where('categories.id', '=', 1);
}])->get();
But it is not working. Any ideas how it should be? Thanks for any help.
The with() function does not actually introduce a join in your query, it just loads the relation of all models as a second query. So the with() function couldn't possibly change the original result set.
What you are looking for is whereHas(). This will add a WHERE EXISTS clause to the existing query.
$doctors = Doctor::with('categories')->whereHas('categories', function ($query) {
$query->where('categories.id', 1);
})->get();
Using ->with() doesn't actually limit the results of the Doctor::...->get() query; it simply tells Laravel what to return in the relationships attribute. If you actually want to enforce returning only Doctors that have a category 1 relationship, you need to use whereHas():
$doctors = Doctor::whereHas('categories', function($query) {
$query->where('categories.id', '=', 1);
// `id` or `categories.id` should work, but `categories.id` is less ambigious
})->get();
You can add whereHas condition for this. Try code below:
$doctors = Doctor::with('categories')->whereHas('categories', function($query) {
$query->where('id', 1);
})->get();

Laravel Nested Eager Loading how to use eloquent where condition from inside with nested

I'm looking for a way to use where condition in my laravel eloquent relationship with eager loading.
Here's my code
$data = Model::with(['stage_chatbot'=> function($stage_chatbot){
$stage_chatbot->select('id', 'customer_id','stage','created_at');
$stage_chatbot->orderBy('id', 'asc');
}])->whereIn('hot_leads_id', $getMaxHl)->orderBy('updated_at', 'desc');
$data->where('stage_chatbot.stage', 'like', 'sampleValue')->get();
return $data;
Thanks!
try this one
using use keyword in laravel
$searchText = "sampleValue";
$data = Model::with(['stage_chatbot'=> function($stage_chatbot) use ($searchText) {
$stage_chatbot->select('id', 'customer_id','stage','created_at')
->where('stage_chatbot.stage', 'like', "%".$searchText."%")
->orderBy('id', 'asc');
}])->whereIn('hot_leads_id', $getMaxHl)->orderBy('updated_at', 'desc')->get();
for more information how to used use keyword in anonymous function see
You can use whereHas() eloquent method like this.
$data = Model::with(['stage_chatbot'=> function($stage_chatbot){
$stage_chatbot->select('id', 'customer_id','stage','created_at');
$stage_chatbot->orderBy('id', 'asc');
}])->whereIn('hot_leads_id', $getMaxHl)->orderBy('updated_at', 'desc');
$data->whereHas('stage_chatbot', function ($stage_chatbot) {
$stage_chatbot->where('stage', 'like', 'sampleValue')
})->get();
return $data;
Define a varibale on your Search Input field or value and pass this through use on your model query
Try this
$search = $request->search;
$data = Model::with(['stage_chatbot'=> function($stage_chatbot) use ($search) {
$stage_chatbot->select('id', 'customer_id','stage','created_at');
$stage_chatbot->where('stage', 'like',$searchText);
$stage_chatbot->orderBy('id', 'asc');
}])->whereIn('hot_leads_id', $getMaxHl)->orderBy('updated_at', 'desc')->get();

Laravel 5.2 Many to Many query relationship with where clause

I have a little problem, I have a table with Movies and another with Genres ex: Action, Adventure etc...
Table names:
movies
movie_genre
genres
I want to fetch all the Movies with the selected Genre ex: Action
$movies = Movie::with('genres')
->when($genre, function ($query) use ($genre) {
return $query->where('genres.id', $genre->id);
})
->paginate(20);
This php code doesn't work, how can I make it work?
PS: The genre is transfered from the view by $_GET['genre'] and stocked in the variable $genre.
Edit after the answer of #Shane and #Marcin NabiaƂek :
The relationship is set in the models and when I use your code directly like this:
Movie::with('genres', 'countries', 'type')
->when($type, function ($query) use ($type) {
return $query->where('medias.type_id', $type->id);
})
->whereHas('genres', function ($query) use ($genre) {
return $query->where('genres.id', $genre->id);
})
->paginate(20);
it work perfectly, but with the when() function it dosn't. I have to use the when() to make the condition work only if there is a genre selected by the user.
You should use whereHas to get all movies that are assigned to given genre:
$movies = Movie::with('genres')
->when($genre, function ($query) use ($genre) {
$query->whereHas('genres', function($q) use ($genre) {
return $query->where('id', $genre->id);
});
})->paginate(20);
In case $genre is only id and not model, you should rather use:
return $query->where('id', $genre);
and in case it's an array (user is allowed to choose multiple genres), you should use:
return $query->whereIn('id', (array) $genre);
I'm not familiar with the when function. I use whereHas:
$movies = Movie::whereHas('genres', function ($query) use ($genre) {
$query->where('id', $genre->id);
})->with('genres')->get();
Also, is $genre the model or the ID? You mentioned it was received from $_GET which would mean it would be an ID probably.
I think a better solution would be to use your relationship function in the Genre model to get them:
$movies = Genre::find($genre_id)->movies;

Laravel - Using a nested relationship with the query builder

I am working on an API but its starting to get a bit slow now that the data is increasing. I am moving some of the queries so that they use the DB query builder.
I have my last one which has a nested query:
$artists = Artist::with('performances', 'performances.stage')->get();
I have got so far:
$artists = \DB::table('artists')
->leftJoin('performances', 'artists.id', '=', 'performances.artist_id')
->get();
But now need to do the second relationship which in the Performance model is:
public function stage()
{
return $this->hasOne('App\Models\Stage', 'id', 'stage_id');
}
Any help on how I do this?
yes you can use eloquent relationship with query builder like this
$artists = Artist::join('performances', 'artists.id', '=', 'performances.artist_id')
->all();
foreach($artists as $artist){
$data = $artist->stage()->first();
}
It is very well covered in the official documentation, please, refer to this section of Documentation
I think that you want to achieve something like this:
$posts = Post::whereHas('comments', function ($query) {
$query->where('content', 'like', 'foo%');
})->get();
And also, please, read carefully this section

Categories