これは「コードを書いていて困ったときに、suinがチャットで質問に答えたり相談に乗るsuinのプログラミング相談室(仮)」で頂いた質問と僕の回答の要約です。
質問
「あああ いいい ううう」のようなスペース区切の単語をSQLでAND検索できるコードを書いてみたのですが、もっと良い書き方ってありませんか?
$keywords = ['A', 'B', 'C', 'D', 'E']; // 回答者注:SQLインジェクションが発生しない安全な文字列と仮定します。
switch (count($keywords)) {
case 1:
$sql = "SELECT * FROM products WHERE name LIKE '%$keywords[0]%'";
break;
case 2:
$sql = "SELECT * FROM products WHERE name LIKE '%$keywords[0]%' AND name LIKE '%$keywords[1]%'";
break;
case 3:
$sql = "SELECT * FROM products WHERE name LIKE '%$keywords[0]%' AND name LIKE '%$keywords[1]%' AND name LIKE '%$keywords[2]%'";
break;
case 4:
$sql = "SELECT * FROM products WHERE name LIKE '%$keywords[0]%' AND name LIKE '%$keywords[1]%' AND name LIKE '%$keywords[2]%' AND name LIKE '%$keywords[3]%'";
break;
case 5:
$sql = "SELECT * FROM products WHERE name LIKE '%$keywords[0]%' AND name LIKE '%$keywords[1]%' AND name LIKE '%$keywords[2]%' AND name LIKE '%$keywords[3]%' AND name LIKE '%$keywords[4]%'";
break;
}
suin: この方法だと、無限にcase
を増やさないとだめですもんね。
質問者: はい、そうなんです。
suinの回答
アルゴリズムに関する質問ですね。手順としては次のように実装します。
- キーワードを
foreach
で回して、name LIKE %xxx%
といったLIKE句の配列を作る。 - 配列を文字列
"AND"
でくっつけて、WHERE句用の文字列を作る。 - 作ったWHERE句用文字列を全体のSQLにくっつける。
$keywords = ['A', 'B', 'C', 'D', 'E']; // 回答者注:SQLインジェクションが発生しない安全な文字列と仮定します。
// キーワードの数だけループして、LIKE句の配列を作る
$keywordCondition = [];
foreach ($keywords as $keyword) {
$keywordCondition[] = 'name LIKE "%' . $keyword . '%"';
}
var_dump($keywordCondition);
// ここで、
// [ 'product_name LIKE "%hoge%"',
// 'product_name LIKE "%fuga%"',
// 'product_name LIKE "%piyo%"' ]
// という配列ができあがっている。
// これをANDでつなげて、文字列にする
$keywordCondition = implode(' AND ', $keywordCondition);
// あとはSELECT文にくっつけてできあがり♪
$sql = 'SELECT * FROM products WHERE ' . $keywordCondition . ' AND ... 他に条件があればここに書く ';
回答に対しての反応
なるほど! やってみます!