laravel Поиск несколько слов, разделенных пробелом

Я новичок в laravel query builder, я хочу искать несколько слов, введенных в поле ввода, например, если я набираю "Jhon doe", я хочу получить любой столбец, содержащий jhon или doe

Я видел / пробовал решения с использованием php MySQL, но не могу адаптироваться к Query builder

//1. exploding the space between the keywords 

//2. using foreach apend the query together

$query = "select * from users where";

$keywordRaw = "jhon doe";
$keywords = explode(' ', $keywordRaw );
foreach ($keywords as $keyword){
$query.= " first_name LIKE '%" + $keyword +"%' OR ";
}

как это сделать с помощью Query builder

это то, что у меня есть до сих пор, каков правильный способ сделать это,

$keywordRaw = "jhon doe";
//how do I explode this words and append them along with their appropriate query
$users = User::select('users.*')
->where('first_name', 'LIKE', '%'.$keywordRaw.'%')

пожалуйста, помогите, спасибо заранее

7 ответов


вот как вы это делаете с Query\Builder, но сначала некоторые дополнительные примечания:

// user can provide double space by accident, or on purpose:
$string = 'john  doe';

// so with explode you get this:
explode(' ', $string);
array(
  0 => 'john',
  1 => '',
  2 => 'doe'
)

// Now if you go with LIKE '%'.value.'%', you get this:
select * from table where name like '%john%' or name like '%%' or ...

тем не менее, вы, очевидно, не можете полагаться на explode потому что в этом случае вы получите все строки.

Итак, вот что вы должны сделать:

$string = 'john  doe';

// split on 1+ whitespace & ignore empty (eg. trailing space)
$searchValues = preg_split('/\s+/', $string, -1, PREG_SPLIT_NO_EMPTY); 

$users = User::where(function ($q) use ($searchValues) {
  foreach ($searchValues as $value) {
    $q->orWhere('name', 'like', "%{$value}%");
  }
})->get();

есть закрытие в where потому что это хорошая практика, чтобы обернуть ваш or where оговорки в скобках. Например, если ваш User модель SoftDeletingScope и вы не сделали бы то, что я предложил, весь ваш запрос все будет испорчено.


 $keywordRaw = "jhon doe";
    $key = explode(' ',$keywordRaw)
    $users = User::select('users.*')
    ->whereIn('first_name',$key);

Это будет работать.where будет искать имя из ключевых слов, которые вы ввели.


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

   $searchQuery = "jhon doe"; 
$searchTerms = explode(" ", $searchQuery); // Split the words
$users = User::whereIn('FirstName', $searchTerms)->get();
print_r($users);

Вы можете попробовать следующие

$keywordRaw = "jhon doe";
$bindArr = explode(" ", $keywordRaw);

$query = "select * from users where";    
foreach ($i = 0; $i < count($bindArr); $i++) {
    if ($i == 0) {
        $query.= ' first_name LIKE "%?%"';
    } else {        
        $query.= ' or first_name LIKE "%?%"';
    }
}

$sth = $dbh->prepare($query);
$sth->execute($bindArr);

вы использовать полнотекстовый индекс на столбце "имя"?

вы можете создать этот индекс с помощью миграции Laravel, хотя вам нужно использовать инструкцию SQL:

DB::statement('ALTER TABLE users ADD FULLTEXT(first_name);');

затем вы можете запустить довольно расширенный поиск в этом поле, например:

$keywordRaw = "john doe";
$keywords   = explode(' ', $keywordRaw);
$users   = User::select("*")
              ->whereRaw("MATCH (first_name)
                          against (? in boolean mode)",[$keywords])
              ->get();

это будет соответствовать записям, содержащим слова "john" или "doe"; обратите внимание, что этот подход будет соответствовать целым словам, а не подстрокам (что может быть, если вы используете ЛЮБИТЬ.)

если вы хотите найти записи, содержащие все слова, вы должны предшествовать каждому ключевому слову с"+", как это:

$keywords   = '+'.explode(' +', $keywordRaw);

вы даже можете сортировать по релевантности, хотя это, вероятно, излишне для ваших нужд (и не имеет значения для "всех" поисков). Что-то вроде этого:--5-->

$users = User::select("*")
               ->selectRaw("MATCH (first_name)
                            against (? in boolean mode)
                            AS relevance",[$keywords])
               ->whereRaw("MATCH (first_name)
                           against (? in boolean mode)",[$keywords])
               ->orderBy('relevance','DESC')
               ->get();

есть хорошая статья, которая охватывает этот общий подход здесь:

http://www.hackingwithphp.com/9/3/18/advanced-text-searching-using-full-text-indexes


вы можете использовать этот пакет https://github.com/nicolaslopezj/searchable

или просто сделайте это, если вы не хотите использовать package

$keywordRaw = "jhon doe";
$users = User::where('first_name', 'LIKE', $keywordRaw.'%')
->orWhere('first_name', 'LIKE', '% '.$keywordRaw.'%')
->get();

$string = 'john  doe';

// split on 1+ whitespace & ignore empty (eg. trailing space)
$searchValues = preg_split('/\s+/', $string, -1, PREG_SPLIT_NO_EMPTY); 

$users = User::where(function ($q) use ($searchValues) {
  foreach ($searchValues as $value) {
    $q->Where('name', 'like', "%{$value}%");
  }
})->get();

использование "orWhere" даст вам результаты для каждого ключевого слова, а не результаты для keyword1 + keyword2...поэтому все зависит от того, что вы ищете