Christopher Reeve
Christopher Reeve

Reputation: 478

Laravel - Querying Eloquent 3 table with conditions

i've been searching everywhere including stackoverflow but still cannot get an answer for my case.

so i've 3 models User,Todo,and TodoItem.

i'm trying to let the user search a todolist and searching based on the todo title or description or the todoitem description.

here is my current code

private function searchTodos(){
        return ModelsTodo::
        where('creator',Auth::user()->id)
        ->with('TodoItem',
            function($q) {
                    $q->where('description','LIKE','%'.$this->search.'%');
            })
        ->where(function($q){
            $q->where('title','LIKE','%'.$this->search.'%')
            ->orWhere('description','LIKE','%'.$this->search.'%');
        })
        ->latest()
        ->paginate($this->perPage);
    }

this can already searching for the todo title and description, but still cannot searching for the todoitem description.

when i try to search for the todoitem description it doesn't found anything.

this is my models relationship

User.php

public function Todos(){
    return $this->hasMany(Todo::class,'creator');
}

Todo.php

public function User(){
    return $this->belongsTo(User::class,'creator');
}
public function TodoItem()
{
    return $this->hasMany('App\Models\TodoItem');
}

TodoItem.php

public function Todo()
{
    return $this->belongsTo('App\Models\Todo');
}

is there anyway to achieve this using eloquent?

i'm relatively new to multiple table relationship using eloquent so i'm very confused how to do this using eloquent.

Upvotes: 0

Views: 47

Answers (1)

mrhn
mrhn

Reputation: 18926

I see two problems, you search logic seems wrong for what i would expect for such a search feature. You are doing the following like search.

todoItem.description like %search% and (title like %search% or description like %search%)

This requires todoItem to have same description as title or description, which seem unlikely?

Secondly with is not a query condition but a filtering aproach to after the model has been found. While I'm not certain that syntax is even correct. You should use whereHas() instead. I believe the following approach would work.

ModelsTodo::where('creator',Auth::user()->id)
    ->where(function ($query) {
        $query->whereHas(
            'TodoItem',
            function($q) {
                $q->where('description','LIKE','%'.$this->search.'%');
            }
        )->orWhere(function($q) {
            $q->where('title','LIKE','%'.$this->search.'%')
                ->orWhere('description','LIKE','%'.$this->search.'%');
            })
        })
    ->latest()
    ->paginate($this->perPage);

This makes your logic into this condition

(todoItem.description like %search% or (title like %search% or description like %search%))

Style and ending notes

  • Don't name your relationships in pascal case, that should be camel case.
  • Be consistent with styles there is a lot of (){ instead of () {
  • Indention is not consistent

Upvotes: 1

Related Questions