Функция поиска с несколькими условиями в Laravel

#laravel #eloquent #laravel-5.7

#laravel #красноречивый #laravel-5.7

Вопрос:

Я попытался создать функцию поиска на основе 4 запросов; categories , location , keyword и sorting . Функция поиска с 3 запросами ( location , categories и sorting ) работает хорошо и имеет корректный вывод.

Но проблема в том, что когда мой веб-сайт отправляет запрос с keywords данными, выходные результаты являются только результатом только keywords запроса, когда я пытаюсь отправить location / categories запросы, выходные данные не меняются (только выходные данные только запроса ключевого слова)

Ответ в формате JSON

Вот код, который я пишу:

     public function getBy(Request $request) {
        $categories = $request->all()['categories'];
        $location   = $request->all()['location'];
        $sorting    = $request->all()['sorting'];
        $keyword    = $request->all()['keyword'];

        //--- sorting code ---

        //keyword request
        if ($keyword === null) {
          $jobs = Job::query();
        } else {
          $jobs = Job::query()->where('job_title', 'LIKE', "%{$keyword}%")
            ->orWhere('title', 'LIKE', "%{$keyword}%")
            ->orWhere('description', 'LIKE', "%{$keyword}%")
            ->orWhereHas('users', function ($q) use ($keyword) {
              $q->where('company_name', 'LIKE', "%{$keyword}%");
            })->orWhereHas('categories', function ($q) use ($keyword) {
              $q->where('category', 'LIKE', "%{$keyword}%");
            })->orWhereJsonContains('tags', $keyword);
        }

        //location and categories request
        if ($location === [] amp;amp; $categories === []) {
          $jobs;
        } elseif ($location === []) {
          $jobs->whereHas('categories', function ($q) use ($categories) {
            $q->whereIn('slugs', $categories);
          });
        } elseif ($categories === []) {
          $jobs->whereHas('location', function ($q) use ($location) {
            $q->whereIn('city_name', $location);
          });
        } else {
          $jobs->whereHas('categories', function ($q) use ($categories) {
            $q->whereIn('slugs', $categories);
          })->whereHas('location', function ($q) use ($location) {
            $q->whereIn('city_name', $location);
          });
        }

        //return as JSON
      }
  

Ответ №1:

Основная проблема с вашим кодом заключается в том, что вы locations и categories поисковый запрос снова не были настроены $jobs . Это должно выглядеть следующим образом:

  $jobs = $jobs->whereHas('categories', function ($q) use ($categories) {
     $q->whereIn('slugs', $categories);
 });
  

Это установит $jobs переменную для включения новых условий запроса.

Я бы также предложил не проверять, являются ли $locations или $categories пустыми, поскольку они, если операторы для каждого из них, уже имеют дело с условием. Вот некоторый переработанный код:

 public function getBy(Request $request) {
    $sorting    = $request->all()['sorting'];

    //--- sorting code ---

    //keyword request
    if (! $keywords = request('keywords')) {
        $jobs = Job::query();
    } else {
        $jobs = Job::query()->where('job_title', 'LIKE', "%{$keyword}%")
            ->orWhere('title', 'LIKE', "%{$keyword}%")
            ->orWhere('description', 'LIKE', "%{$keyword}%")
            ->orWhereHas('users', function ($q) use ($keyword) {
                $q->where('company_name', 'LIKE', "%{$keyword}%");
            })->orWhereHas('categories', function ($q) use ($keyword) {
                $q->where('category', 'LIKE', "%{$keyword}%");
            })->orWhereJsonContains('tags', $keyword);
    }

    foreach (['categories', 'locations'] as $field) {
        if ($request->filled($field)) {
            $jobs = $jobs->whereHas($field, function ($q) use ($field) {
                $q->whereIn('slugs', request($field));
            });
        }
    }

    return $jobs->get()->toArray();
}
  

Здесь мы перебираем данные categories и locations запрашиваем данные и смотрим, являются ли данные ->filled() (определены и не пусты). Если это так, мы выполняем запрос.

Комментарии:

1. мой API получает categories и locations в виде пустого массива [] , если мы не вводили эти условия. Кроме того, если все мои входные данные запроса пусты, он должен показать весь запрос.

2. ->filled() справится с этим, поскольку она не будет обрабатывать, если она определена и если она пуста. Кроме того, если keywords не пройти через нее, она все равно вернет все результаты.

Ответ №2:

Попробуйте это

  public function getBy(Request $request) {
    $categories = $request->categories;
    $location   = $request->location;
    $sorting    = $request->sorting;
    $keyword    = $request->keyword;

    //--- sorting code ---


    $jobs = Job::query();

    //keyword request
    if ($keyword !== null) {
      $jobs = $jobs->where('job_title', 'LIKE', "%{$keyword}%")
        ->orWhere('title', 'LIKE', "%{$keyword}%")
        ->orWhere('description', 'LIKE', "%{$keyword}%")
        ->orWhereHas('users', function ($q) use ($keyword) {
          $q->where('company_name', 'LIKE', "%{$keyword}%");
        })->orWhereHas('categories', function ($q) use ($keyword) {
          $q->where('category', 'LIKE', "%{$keyword}%");
        })->orWhereJsonContains('tags', $keyword);
    }

    //location and categories request
    if ($location === []) {
      $jobs = $jobs->whereHas('categories', function ($q) use ($categories) {
        $q->whereIn('slugs', $categories);
      });
    } elseif ($categories === []) {
      $jobs = $jobs->whereHas('location', function ($q) use ($location) {
        $q->whereIn('city_name', $location);
      });
    } else {
      $jobs = $jobs->whereHas('categories', function ($q) use ($categories) {
        $q->whereIn('slugs', $categories);
      })->whereHas('location', function ($q) use ($location) {
        $q->whereIn('city_name', $location);
      });
    }

    return $jobs->get();
  }
  

Комментарии:

1. выдаваемый результат является только пустым массивом, если нет запроса на ввод. Если запрос на ввод не получен, должны отображаться все данные