как я могу искать несколько ключевых слов в laravel?

это мой контроллер

 $term = $request->get('q');

 // return $request->q;

 $products = Post::whereHas('user', function($query) use($term) {
     $query->where('name', 'like', '%'.$term.'%');
 })->orWhere('tags','LIKE','%'.$term.'%')->get();
 return view('pages.search', compact('products','users'));

Это хорошо работает для поиска по одному ключевому слову. Но я хочу использовать его для нескольких ключевых слов. Например, laravel php и т. Д. Пожалуйста, помогите мне, когда я ищу несколько значений, таких как abc php laravel или что-то еще, тогда это должно работать. Если теги существуют в другом столбце, например, php присутствует в 1-м столбце, а laravel находится в следующем столбце, когда я ищу php laravel, он должен показать мне оба значения столбца.


person Muhammad Haroon    schedule 16.10.2017    source источник


Ответы (3)


Вероятно, есть лучший способ сделать это, например, использовать CloudSearch/Algolia, но это решение сработало для нас:

// Split the terms by word.
$terms = explode(" ", request('q'));

$products = Post::query()
    ->whereHas('user', function ($query) use ($terms) {
        foreach ($terms as $term) {
            // Loop over the terms and do a search for each.
            $query->where('name', 'like', '%' . $term . '%');
        }
    })
    ->orWhere(function ($query) use ($terms) {
        foreach ($terms as $term) {
            $query->where('tags', 'like', '%' . $term . '%');
        }
    })
    ->get();
person Jono20201    schedule 16.10.2017
comment
@AlexeyMezenin Нет необходимости повторно назначать запрос или возвращать его. Это отсылка. Кроме того, это зависит от вашего варианта использования, но я думал, что Laravel удалил возможность делать orWhere, когда вы изначально не делали where. - person Jono20201; 16.10.2017
comment
Я только что проверил это, и это не работает. Вам не нужно повторно назначать запрос, но вы не можете просто использовать ->where в цикле или замыкании, как вы это делаете. Итак, вам нужно переназначить $posts, как я показал в своем коде, и построить группу orWhere, а для части whereHas() это должен быть один where и группа orWhere(). - person Alexey Mezenin; 16.10.2017
comment
@AlexeyMezenin Вы изменили свой код с момента моего последнего комментария, чтобы удалить часть, о которой вы говорили в своем первоначальном комментарии, который вы также удалили. Код, показанный в моем ответе, должен работать без проблем и работает на одном из наших производственных сайтов. - person Jono20201; 16.10.2017
comment
Да, я проверил и свой код, и ваш, и отредактировал код, после чего добавил предыдущий комментарий. Ваш код не работает, я проверял. - person Alexey Mezenin; 16.10.2017
comment
Вы были правы в переназначении $query->where, но OP все равно нужно будет переназначить $posts (или любую другую переменную) после того, как он добавит несколько orWhere. - person Alexey Mezenin; 16.10.2017
comment
также дает тот же результат, что и я. но только для тегов одного столбца. но это хорошо - person Muhammad Haroon; 16.10.2017
comment
@MuhammadHaroon Этот код просто не может работать для вас по двум причинам, которые я описал. - person Alexey Mezenin; 16.10.2017
comment
@AlexeyMezenin этот код работает только для одного столбца. я имею в виду, когда я ввожу ключевые слова тега в поиске, он находит тег столбца и код поиска. но если оба ключевых слова присутствуют в столбце тегов, то он работает, но если один присутствует, а второй нет, то он ничего не показывает. . но он работает, если два или более ключевых слова верны. - person Muhammad Haroon; 16.10.2017
comment
@MuhammadHaroon это потому, что этот код использует AND как для моделей User, так и для Post, и вам нужно OR - person Alexey Mezenin; 16.10.2017
comment
я просто добавляю orwhere в последний цикл foreach, теперь он работает хорошо. имя пользователя с тегом поста - person Muhammad Haroon; 16.10.2017
comment
@MuhammadHaroon Рад, что смог помочь, не стесняйтесь принять этот ответ, если он решил вашу проблему. - person Jono20201; 16.10.2017
comment
@MuhammadHaroon, даже если вы измените where на orWhere в последнем цикле, это не сработает, потому что для модели пользователя все равно будет использоваться AND вместо OR. Я объяснил все в своем ответе час назад. - person Alexey Mezenin; 16.10.2017
comment
да, это И @AlexeyMezenin, но как я могу изменить его на или . ваш код дает ошибку. не могли бы вы сказать мне ваш код. потому что код, который вы опубликовали, дает мне некоторую ошибку. публичная функция searchme(Request $request){ $term = $request->get('q'); $products = Post::whereHas('user', function($query) use($term) { $query-›where('name', 'like', '%'.$term.'%'); - ›orwhere('электронная почта', 'лайк', '%'.$term.'%'); })-›orWhere('tags','LIKE','%'.$term.'%')-› получить(); return view('pages.search', compact('products','users')); } это полная функция поиска - person Muhammad Haroon; 17.10.2017
comment
этот код показывает мне результат только первого параметра тега, когда я использовал второй тег и не использовал значение первого тега, это ничего не показывает - person Muhammad Haroon; 17.10.2017

Сначала вам нужно подготовить массив $terms, а затем просто перебрать его и добавить предложения orWhere().

Я только что протестировал его, и для закрытия whereHas() вам нужно использовать where() для первого термина и orWhere()для остальных, чтобы он работал:

$posts = Post::whereHas('user', function($q) use($terms) {
        $q->where('name', 'like', '%' . $term .'%');

        foreach (array_slice($terms, 1) as $term) {
            $q->orWhere('name', 'like', '%' . $term .'%');
        }
    });

foreach ($terms as $term) {
    $posts->orWhere('tags', 'like', '%' . $term . '%');
}

$posts = $posts->get();

Если вы решите использовать = вместо like, просто используйте whereIn() вместо создания запроса с набором orWhere().

person Alexey Mezenin    schedule 16.10.2017
comment
Ошибка синтаксического анализа: синтаксическая ошибка, неожиданный foreach (T_FOREACH) - person Muhammad Haroon; 16.10.2017
comment
foreach (array_slice($terms, 1) as $term) показывает здесь ошибку - person Muhammad Haroon; 16.10.2017
comment
Ошибка синтаксического анализа: синтаксическая ошибка, неожиданное ';', ожидание ',' или ')' снова - person Muhammad Haroon; 16.10.2017
comment
может быть, ваш код сработал, но у меня возникла синтаксическая ошибка. где вы закрываете фигурные скобки }; перед вторым foreach . - person Muhammad Haroon; 16.10.2017
comment
@MuhammadHaroon, как я уже сказал, сначала нужно подготовить массив. Итак, $terms должен быть массивом или ключевыми словами. - person Alexey Mezenin; 16.10.2017
comment
можно сделать этот массив. я не понимаю. я запутался в методе взрыва. - person Muhammad Haroon; 16.10.2017
comment
@MuhammadHaroon, вы не показали исходную строку с полученными терминами. - person Alexey Mezenin; 16.10.2017
comment
Хороший. Единственный рабочий ответ здесь и единственный, который был действительно протестирован, получил отрицательную оценку. Если вы будете отрицать такие ответы, SO оставит парней, которые могут только копировать и вставлять материал и не могут помочь с реальной проблемой. - person Alexey Mezenin; 16.10.2017
comment
публичная функция searchme(запрос $request){ - person Muhammad Haroon; 17.10.2017
comment
2-я строка $terms = $request->get('q'); - person Muhammad Haroon; 17.10.2017
comment
какую еще строку ты просишь, братан :) - person Muhammad Haroon; 17.10.2017
comment
я получаю сообщение об ошибке после разделения. преобразование массива в строку во второй строке вашего кода - person Muhammad Haroon; 17.10.2017
comment
дорогой, я решил ошибки и получил значения с помощью обратных сообщений, но сообщения не отображаются для просмотра. я сталкиваюсь с этой проблемой второй раз. перед этим кодом я объединил два массива и сохранил их в какую-то переменную, эта переменная также не была получена в поле зрения, и теперь второй раз в вашем коде, где вы добавили сообщения = сообщения-> get () это показывает результат на контроллере, возвращая сообщения, но это не переходя к view.view show empty.but другой код john, который является AND, но его переменная получает в view.problem post-posts->get .bcz я уже сталкивался с этой проблемой.он показывает значение на контроллере, но не в Посмотреть - person Muhammad Haroon; 17.10.2017
comment
этот код показывает мне результат только первого параметра тега, когда я использовал второй тег и не использовал значение первого тега, это ничего не показывает - person Muhammad Haroon; 17.10.2017

Я потратил много времени на это за последние пару дней, и вот мое решение. Он похож на эти другие, но отличается, поэтому однажды может кому-то пригодиться:

У меня есть компонент Vue, который делает запрос GET, поэтому $request->get('searchTerms') исходит из <input name="searchTerms"> в форме отправки HTML.

Я хотел, чтобы пользователь мог контролировать, какие поля будут искать, поэтому $search_terms — это массив столбцов для поиска.

Я хотел, чтобы, если пользователь искал «Макдональдс 604», он отфильтровывал список записей и показывал два разных совпадения для этого поиска. Одно совпадение «Макдональдс» для business_name и одно совпадение «604» для кода города phone_number. Это гарантировало бы, что пользователь получит все, что связано, если он знает только некоторые фрагменты.

Цель состояла в том, чтобы перебирать условия поиска, а также перебирать поля поиска (столбцы) с общей формулой, которую можно было применять из любого количества условий поиска и столбцов, динамических во время выполнения.

        $search_fields = ['project_name', 'business_name', 'phone_number'];
        $search_terms = explode(' ', $request->get('searchTerms'));

        $query = Campaign::query();
        foreach ($search_terms as $term) {
            $query->orWhere(function ($query) use ($search_fields, $term) {

                foreach ($search_fields as $field) {
                    $query->orWhere($field, 'LIKE', '%' . $term . '%');
                }
            });
        }
        $filtered = $query->get();

Я бы порекомендовал прочитать документацию по запросам для Laravel, потому что это даст вам лучшее представление об этой задаче: https://laravel.com/docs/5.6/queries

В приведенном выше коде мы используем parameter grouping, и он изменяет характеристики алгоритма, если вы используете where вместо orWhere.

Бонусные факты

Я также настоятельно рекомендую протестировать ваши операторы SQL, используя $query->toSql() и $query->getBindings(). Вы можете поместить их вместо $query->get(), чтобы увидеть, как будет выглядеть генерируемый оператор SQL и каковы привязки параметров. getBindings() покажет вам, какие значения ? находятся в toSql().

person agm1984    schedule 20.09.2018