WhereNotIn inside WhereHas - laravel

why whereNotIn doesn't work inside whereHas?
Model::whereHas('statuses', function ($query) {
$query->whereNotIn('title',['X,'Y','Z']);
})
I posted as answer workarounds but can someone explain it or it's BUG?
Laravel 6

Some workarounds:
->whereDoesntHave('statuses', function ($query) {
$query->whereIn('title',['X','Y','Z']);
})
or
->whereHas('statuses', function ($query) {
$query->whereIn('title', ['X,'Y','Z']);
$query->having(\DB::raw("COUNT(table_statuses.id)"), '=', 0);
})

It's not a bug, it only works if the relationship is one to one if it one to many you have to use whereDoesnHave

Related

Laravel 5.8 whereHasMorph "dot" syntax not supported?

Laravel 5.8 introduced whereHasMorph for querying polymorphic relationships. https://laravel.com/docs/5.8/eloquent-relationships#querying-relations
I might be missing something, but it doesn't seem to support dot syntax.
In a regular relationship, I would be able to do something like:
$comments->whereHasMorph(
'video.someRelationship', function ($query) {
$query->where(...);
});
But with whereHasMorph that doesn't seem to work:
$comments->whereHasMorph(
'commentable.someRelationship',
[Video::class, Audio::class],
function ($query) {
$query->where(...);
}
);
If it's indeed not supported, is there a way around it?
whereHasMorph() doesn't (and can't) support the "dot syntax".
Use whereHas() inside the closure for the nested relationship:
$comments->whereHasMorph(
'commentable',
[Video::class, Audio::class],
function ($query) {
$query->where(...) // Constraint on "commentable"
->whereHas('someRelationship', function ($query) {
$query->where(...); // Constraint on "someRelationship"
});
}
);

Only one whereHas is working in deep eloquent relationship

I have a deep eloquent relation.
What I’m trying to do is filter the actions.treatmentActions.treatment.date with $date_range and actions.treatmentActions.paid which equal 1. The date_range filter is working fine, but the paid filter isn’t. The collection is still including the actions.treatmentActions.paid that equal to 0
Any thought on this? am I missing something?
$polis = Poli::with('actions')
->whereHas('actions.treatmentActions.treatment', function ($treatment) use ($date_range){
$treatment->whereBetween('date', $date_range);
})
->whereHas('actions.treatmentActions', function ($treatmentActions){
$treatmentActions->where('paid', 1);
})
->where('id', '!=', 4)
->get();
I've tried different approach like this, but still not working:
$polis = Poli::with('actions')
->whereHas('actions', function ($actions) use ($date_range){
$actions->whereHas('treatmentActions', function ($treatmentActions) use ($date_range){
$treatmentActions->whereHas('treatment', function ($treatment) use ($date_range){
$treatment->where('paid', 1)->whereBetween('date', $date_range);
});
});
})
->where('id', '!=', 4)
->get();
Fixed it with callback in with
$polis = Poli::with(['actions.treatmentActions' => function($query){
$query->where('paid', 1);
}])
->whereHas('actions.treatmentActions.treatment', function ($treatment) use ($date_range){
$treatment->whereBetween('date', $date_range);
})
->get();
Anyone can link me an article explaining this?

laravel - send a selected field to with function

how can i use "airpot_id" in with function?
City::select([
"cities.id",
"airports.id As airport_id"
])
->RightJoin('airports', function ($join)
{
$join->on('cities.id', '=', 'airports.city_id');
})
->with(["airports" => function ($q)
{
$q->where("id",airport_id) //I want to use here.
}])
->paginate(env("PER_PAGE", 10))->toArray();
Why are you using joints like this? Use the eloquent query builder. Maybe you should post you modal, relations and your objective. In general, if we need to pass value inside function we use use($variable). Something like this
$airport_id = 1;
$data = City::with(["airports" => function ($q) use($airport_id){ //Like this we pass data
$q->where("id",airport_id)
}])->get();
I don't think this will work in your case

Sort collection by relationship value

I want to sort a laravel collection by an attribute of an nested relationship.
So I query all projects (only where the project has tasks related to the current user), and then I want to sort the projects by deadline date of the task relationship.
Current code:
Project.php
public function tasks()
{
return $this->hasMany('App\Models\ProjectTask');
}
Task.php
public function project()
{
return $this->belongsTo('App\Models\Project');
}
UserController
$projects = Project->whereHas('tasks', function($query){
$query->where('user_id', Auth::user()->id);
})->get()->sortBy(function($project){
return $project->tasks()->orderby('deadline')->first();
});
I don't know if im even in the right direction?
Any advice is appreciated!
A nice clean way of doing this is with the . operator
$projects = Project::all()->load('tasks')->sortBy('tasks.deadline');
I think you need to use something like join() and then sort by whatever you need.
For exapmle:
Project::join('tasks', 'tasks.project_id', '=', 'projects.id')
->select('projects.*', DB::raw("MAX(tasks.deadline) as deadline_date"))
->groupBy('tasks.project_id')
->orderBy('deadline_date')
->get()
Update
Project::join('tasks', function ($join) {
$join->on('tasks.project_id', '=', 'projects.id')
->where('tasks.user_id', Auth::user()->id)
->whereNull('tasks.completed');
})
->select('projects.*', DB::raw("MAX(tasks.deadline) as deadline_date"))
->groupBy('tasks.project_id')
->orderBy('deadline_date')
->get()
Update2
Add with in your query as:
->with(['tasks' => function ($q) {
$q->where('user_id', Auth::user()->id)
->whereNull('completed');
})
Try This,
$tasks = Task::with('project')
->where('user_id',Auth::user()->id)
->orderBy('deadline')
->get();
After that you can access project properties like below
$tasks->first()->project()->xxx

Getting a relationship with a condition?

I have category and article tables, they are in a many to many relationship. i have the relationships set up on the models.
How can I get all articles where a category id is = 1?
I've tried:
Article::whereHas('category', function ($query) use ($id) {
$query->where('category_id', $id);
})->get();
The above works, but seems clunky, is there a more efficient way in eloquent to do this?
You can use eager loading technique.
Article::with(['category', function ($query) use ($id) {
$query->where('category_id', $id);
}])->get();
The following groupBy code is assuming that Category::find($id)->articles is not an option for whatever reason.
What about groupBy?
Article::groupBy('category')
->having('category', $id)
->get();
whereHas will return articles that match that condition, but won’t filter articles then fetched by the same conditions. You could therefore create an anonymous function that contains the constraints, and pass it to both the whereHas and with methods:
$filter = function ($query) use ($categoryId) {
$query->where('category_id', '=', $categoryId);
};
Article::whereHas('category', $filter)
->with(['category' => $filter])
->get();

Resources