laravelクエリビルダーを初めて使用します。たとえば、「jhon doe」と入力した場合、入力フィールドに入力された複数の単語を検索したいです。jhonまたはdoeを含む列を取得したいです。
Php MySQLを使用したソリューションを見たり試したりしましたが、クエリビルダーに適応できません
//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 ";
}
クエリビルダーを使用してこれを行うにはどうすればよいですか
これは私がこれまでに持っているものです、これを行う適切な方法は何ですか、
$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.'%')
助けてください、事前に感謝します
これは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();
or where
句を括弧で囲むことをお勧めするため、where
にはクロージャがあります。たとえば、User
モデルがSoftDeletingScope
を使用していて、私が提案したことを実行しない場合、クエリ全体が台無しになります。
$keywordRaw = "jhon doe";
$key = explode(' ',$keywordRaw)
$users = User::select('users.*')
->whereIn('first_name',$key);
これは機能します。whereInは入力したキーワードから名を検索します。
これを試してください..
$searchQuery = "jhon doe";
$searchTerms = explode(" ", $searchQuery); // Split the words
$users = User::whereIn('FirstName', $searchTerms)->get();
print_r($users);
First_name列にFULLTEXTインデックスを使用することを検討しましたか?
このインデックスは、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」という単語を含むレコードと一致します。このアプローチは、部分文字列ではなく単語全体に一致することに注意してください(LIKEを使用する場合に当てはまります)。
allの単語を含むレコードを検索する場合は、次のように、各キーワードの前に「+」を付ける必要があります。
$keywords = '+'.explode(' +', $keywordRaw);
関連性で並べ替えることもできますが、これはおそらくニーズには行き過ぎです(「すべての」検索には関係ありません)。このようなもの:
$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
次のように試すことができます
$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);
$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の結果ではなく各キーワードの結果が得られます...したがってすべてはあなたが探しているものに依存します
このパッケージを使用できます https://github.com/nicolaslopezj/searchable
または、パッケージを使用したくない場合は、これを実行してください
$keywordRaw = "jhon doe";
$users = User::where('first_name', 'LIKE', $keywordRaw.'%')
->orWhere('first_name', 'LIKE', '% '.$keywordRaw.'%')
->get();