Home > Software engineering >  How to write an Eloquent query in Laravel 8 for an unknown number of orWhere conditions
How to write an Eloquent query in Laravel 8 for an unknown number of orWhere conditions

Time:10-15

I have been searching and searching and I cannot find an answer to this question. I need to make a query where I will have a dynamic number of OR clauses. The documentation seems to suggest it is possible to pass an array of conditions to either where or orWhere, and yet when I try to do this, I end up with no results.

The query I need to make looks something like this:

SELECT * FROM tags WHERE name = $name1 OR name = $name2 ... OR name = $nameN;

I created an array of conditions and passed them to orWhere like so:

// a user's tags for which all corresponding questions are queried
$user = User::with('tags')-where('id', Auth::user()->id)-get();

// an array of conditions formatted like the docs specify
$conditions = $user->tags->map(function ($item) {
    return ['name', '=', $item->name];
})->all();
/* 
outputs a plain array like this: 

[
  ["name", "=", "php"],
  ["name", "=", "mysql"],
  ["name", "=", "laravel"],
]
*/

$tags = Tag::with([
    'questions.answers', 
    'questions.user.answers',
    'questions.tags'
])
->orWhere($conditions)
->get();

The result should be a collection of tags matching the user's tags, along with their related questions. But instead I get nothing. I have tried re-writing this query in a bunch of different ways and without eager loading related data as well, and nothing makes a difference. If I add a where clause before the orWhere clause, then the query returns only data filtered by the where clause.

I'm at my wits' end with this. I have figured out a work-around, but it's complicated and really not ideal. I should be able to just use a simple orWhere with an array of conditions rather than resorting to complicated hacks. Can anyone point out what I'm doing wrong and/or how I can achieve the results I'm trying to get? Thanks in advance.

CodePudding user response:

Have you tried something like this:

// For the first time, you need to use where statement
$tags = Tag::where(...);

// Then for the remaining conditions, you could use looping
// for chaining the orWhere statements
foreach ($queryStatements as $statement) {
    $tags = $tags->orWhere(...);
}

// Then after all queries have been applied, call the get() method
$res = $tags->get();

This is how I would do it, hope this helps!

CodePudding user response:

Do you already try use the in clause on where?

CodePudding user response:

If you put an array inside orWhere() method. Your query is gonna be like this:

`select * from `tags` where (`name` = ? and `name` = ? and `name` = ?) and `tags`.`deleted_at` is null`

As you can see the that it's search and for every item you put in. So here's how i solve the problem:

$query = Tag::with([
    'questions.answers',
    'questions.user.answers',
    'questions.tags'
])->query();
//Foreach item in array
foreach ($datas as $data) {
    $query->orWhere('name', '=', $data);
}
//Excute the query
$tags = $query->get();

Hope this solve your problem.

CodePudding user response:

If you just want to find tags by name you can use the whereIn() method.

// Get array of current authenticated user's tags
$tags = auth()->user()->tags()->pluck('name');

/*
    outputs an array like this:
    ['php', 'laravel', 'mysql']
*/

$tags = Tag::with([
    'questions.answers',
    'questions.user.answers',
    'questions.tags'
])
    ->whereIn('name', $tags)
    ->get();


NOTE: The first argument for whereIn() method is the column name you want to search in and the second argument is the array of values you are searching for.

  • Related