データベースサイトで絞り込み検索を実装する方法

記事上部注釈
弊サイトでは実際に利用したサービスなどをアフィリエイトリンク付きで紹介することがあります

カタログ型コンテンツ。一定の範囲で情報を並べるコンテンツです。そのコンテンツが増えてくると検索機能を実装したくなります。その方法論を記します。

写真1. 弊サイトのカタログ型コンテンツの例、東横線撮り鉄スポット

完成系の提示

まず、完成系を示します。

東急東横線撮り鉄スポット検索システム

この検索システムでは私が見つけた64か所について、以下の情報で検索することができます。

  • 編成写真を撮影できるかどうか(全く不可、編成の一部なら可能、8両編成一気に撮影可能)
  • 最寄駅からの徒歩時間(制約なし、10分以内、5分以内)
  • 列車を撮影する際の向き(制約なし、北向きに限定など)

この区分については賛否両論あるかもしれません。ただし、本記事では撮り鉄の心構えやテクニックを述べるのではなく、検索システムを自作することが目的なので、検索項目についての議論はやめましょう。

ここで述べたいのは、単独でフィルターをかけるのではなく、複数のフィルターをかけることです。例示した「東横線撮り鉄スポット検索システム」では「駅から徒歩10分以内」かつ「編成写真を撮影可能」な撮影スポットを絞り込むことができます。

この考えかたは鉄道写真を撮影する場所を絞り込むシステムだけに適用できるものではありません。応用例を挙げてみます。

  • 鎌倉の寺社仏閣を紹介するサイトにおいて、「宗派」と「地域(北鎌倉、鎌倉、長谷など)」で絞り込む
  • 新宿の飲食店を紹介するサイトにおいて、「料理」と「地域」で絞り込む

もちろん、絞り込む軸は2つでなく、3つ以上でも構いません。

※本記事ではPHPについての知識が必要になります。以下の書籍を手元に置くとスムーズでしょう。

マイナビ出版 たにぐち まこと
松浦 健一郎、司 ゆき(共著) SBクリエイティブ

事前準備:データベースを作成

写真2. 撮影スポットにも多くの場所がある(東横フラワー緑道平川町橋)

これからの作業は「データベースに登録された情報を検索し、検索条件に当てはまる条件を絞り込む」という方針です。そのため、データベースに登録することが前提です。

本記事を読んでいる人の多くはWordPress利用者で、独自でサーバーと契約を結んでいると思います。サーバー上にMySQLというソフトを利用できるはずです。私はロリポップちゃんの安いプランを契約していますが、データベースを設定できます。左上の「サーバーの設定・管理」というメニューバーから「データベース」を選ぶことでデータベースに入れます。

本番:検索用PHPファイルを作成

写真3. 方向幕のエラーか?(実際は正当な挙動です、大和路快速の奇妙な表示)

ソースコードの提示

いよいよ本番です。検索用PHPファイルを作成します。

自分のパソコン上で新しくPHPファイルを作成します。私はnotepad++というフリーソフトを活用しています。

簡単のために駅からの徒歩と編成写真の2つから絞り込むソースコードを表示しています(表1)。

表1. 絞り込みのためのソースコード

  1. <?php
  2. データベースへの接続のため省略
  3. $hensei = filter_input(INPUT_POST, "henseiselect");
  4. $toho = filter_input(INPUT_POST, "tohoselect");
  5. if(empty($toho)){
  6. echo'
  7. <form method="post">
  8. <p>編成写真でどのくらいこだわりますか。下の条件から選んでください。
  9. <br>
  10. <select name="henseiselect">
  11. <option value="0">こだわらない</option>
  12. <option value="1">多少こだわる</option>
  13. <option value="2">それなりにこだわる</option>
  14. </select>
  15.     <br></p>
  16. <p>駅からの徒歩にどのくらいこだわりますか。下の条件から選んでください。
  17. <br>
  18. <select name="tohoselect">
  19. <option value=100>徒歩時間指定なし</option>
  20. <option value=10>徒歩10分以内</option>
  21. <option value=5>徒歩5分以内</option>
  22. </select>
  23. <br>
  24. </p>
  25. <input type="submit" value="確定">
  26. </form>';
  27. }
  28. else{
  29. $henseikubetsu = ['編成写真にこだわりはない','編成写真に多少こだわる','編成写真にそれなりにこだわる'];
  30. $records = $dbh->query('select count(*) from データベース名 where toho<='.$toho.' AND hensei2 >='.$hensei.';');
  31. $record = $records->fetch();
  32. echo '<p>今回の条件に合う撮影スポットは<b>';
  33. echo $record['count(*)'];
  34. echo '件</b>です。</p>';    
  35. echo '<p>編成写真へのこだわり<b>:';
  36. print ($henseikubetsu[$hensei]);
  37. echo '</b><br>写真の向きへのこだわり<b>:';
  38. print ($mukikubetsu[$muki]);
  39. echo '</b><br>アクセス:駅から<b>徒歩';
  40. echo $toho;
  41. echo '分以内</b></p><br>の条件を満たす場所は以下の通りです。';
  42. foreach ($dbh->query('select * from データベース名 where toho<='.$toho.' AND hensei >='.$hensei.;') as $row){
  43.      echo '<div>';
  44.      echo '<p>';
  45.      echo'<a href="',$row['URL'],'>',$row['picture'],'<br>';    
  46.         echo '地点:',$row['name'],'</a><br>';
  47.         echo '最寄駅:',$row['eki'],'<br>';
  48.         echo '徒歩:',$row['toho'],'分','<br>';
  49.      echo '向き:',$row['muki'],'<br>';
  50.      echo '編成写真:',$row['hensei'],'<br>';
  51.         echo '</p>';
  52.      echo '</div>';
  53.     }
  54. ?>

このポイントを詳細に解説しましょう。

苦労したのは以下の2つです。その3つについて解説します。

  • 関数に入れるのが数字でないとエラーとなる
  • 検索条件入力前だとfetch()がエラーとなる

今回使用する関数:filter_input

今回使用する関数はfilter_inputです。簡単にいうと、外部からの入力された条件をフィルターとして通し、それに合致するものを出力するというものです。

今回は、

$hensei = filter_input(INPUT_POST, "henseiselect");

としています。POSTで入力された"henseiselect"という条件で与えられた数値を変数として保持するということです。henseiselectで選択された値が2であれば、変数$henseiは2ということです。

関数に入れるのが数値データでないとエラー

最初は編成写真について○、△、×でデータベースに登録していました。しかし、これだとエラー表示が出てしまいます。数値データとなっていた駅からの徒歩分数だけで検索条件を設定したらこのような不具合はなくなりました。そのため、編成写真の「○」「△」「×」が文字データであることが不適切な原因と判断しました。

そこで、○=2、△=1、×=0という数字に置き換え、数値データとして処理することにしました。

検索条件入力前だとfetch()がエラーとなる

複数の条件を絞り込んだ場合、条件に合致する件数がいくつかという情報も重要でしょう。そのために、

$record = $records->fetch();

という関数を導入しています。事前に

$records = $dbh->query('select count(*) from データベース名 where toho<='.$toho.' AND hensei2 >='.$hensei.';');

と変数を定義しています。両方の条件に合致する配列を定義し、そのデータ数を取り出しています。

※fetch文については外部サイトを参照してください。

ただし、これだけだとエラーとなってしまいます。ここで$tohoという変数は検索する際の条件です(19行目~21行目)。検索条件を選択する前だと変数$tohoが未定義なので、処理できません。

そこで、私は考えました。そして、条件入力前と入力後に処理を変えれば良いことに気づきました。今回は最初に変数を2つ定義していますが、検索条件入力後はどれか1つの条件は入力されているはずです。そこで、変数$tohoが定義されている場合と未定義の場合で処理を分けました。

表2. 質問か検索結果の条件分け

  1. <?php
  2. データベースへの接続のため省略
  3. $hensei = filter_input(INPUT_POST, "henseiselect");
  4. $toho = filter_input(INPUT_POST, "tohoselect");
  5. if(empty($toho)){
  6. $tohoが空白のときは質問文を入力
  7. }
  8. else{
  9. $tohoに何からの値が入っているときはデータベースを返す
  10.     }
  11. ?>

ここでのポイントはif(empty($toho))です。empty($○○)は$○○が空白かどうかを確認するための関数です。

※empty関数については外部サイトをご参照ください。

if文は正しいときの処理、正しくないときの処理を書きます。

  • empty($toho)が正しいということは、$tohoが定義されていないので、検索条件を入力してもらう必要あり
  • empty($toho)が正しくない(=空白ではない)ということは、検索結果の処理が可能

こうしてエラーを回避したのでした。

参考:配列の定義とループ

ここでは、そこまで手間取りませんでしたが、配列の定義とループについて述べます。

  1. $henseikubetsu = ['編成写真にこだわりはない','編成写真に多少こだわる','編成写真にそれなりにこだわる'];
  2. echo '<p>編成写真へのこだわり<b>:';
  3. print ($henseikubetsu[$hensei]);
  4. echo '</b><br>写真の向きへのこだわり<b>:';
  5. print ($mukikubetsu[$muki]);
  6. echo '</b><br>アクセス:駅から<b>徒歩';
  7. echo $toho;
  8. echo '分以内</b></p><br>の条件を満たす場所は以下の通りです。';
  9. foreach ($dbh->query('select * from データベース名 where toho<='.$toho.' AND hensei >='.$hensei.;') as $row){
  10. echo '<div>';
  11. echo '<p>';
  12. echo'<a href="',$row['URL'],'>',$row['picture'],'<br>';????
  13. echo '地点:',$row['name'],'</a><br>';
  14. echo '最寄駅:',$row['eki'],'<br>';
  15. echo '徒歩:',$row['toho'],'分','<br>';
  16. echo '向き:',$row['muki'],'<br>';
  17. echo '編成写真:',$row['hensei'],'<br>';
  18. echo '</p>';
  19. echo '</div>';
  20. }

ここで、

$henseikubetsu = ['編成写真にこだわりはない','編成写真に多少こだわる','編成写真にそれなりにこだわる'];

と配列を定義しています。あらかじめ0~2に決めていた数字とそれに対するコメントです。配列は0からスタートしますので、データベースに0点から得点を付けていた自分の有能ぶりさに驚きました。

print ($henseikubetsu[$hensei]);

というprint文で($henseikubetsu[$hensei])を表記しています。これは$henseiという変数が0~2の場合でそれぞれコメントを表記しています。例えば、$hensei=1の際は、$henseikubetsu[$hensei]は$henseikubetsu[1]とみなすことができ、これは上の定義で「編成写真に多少こだわる」に相当します。こうして検索条件に入れた条件を出力し、(読者側に)より分かりやすくしています。

あとは、foreach文で条件に相当する撮影ポイントについて写真、URL、地点名、駅からの徒歩といった詳細条件を出力しています。foreach文は配列を繰り返し処理するためのものです。

なお、私は東横線撮り鉄スポット検索結果については、PCで横3列、モバイルで横2列で出力しています。私はgridというCSSクラスを定義し、それを弊サイトでも導入していますので、そのクラスをforeach文の外側に入れています。また、foreach文の中にdivというタグを入れています。

この詳細は本記事では執筆いたしません。以下の関連記事をご覧ください。

絞り込み検索可能なデータベースを作ってみて

今回、2つ以上の条件で絞り込み検索が可能なデータベースを作ってみました。本記事執筆段階では東横線撮り鉄スポット検索システム山手線撮り鉄スポット検索システムだけですが、自分のスキル向上のみならず、撮り鉄スポットを検索する際の検索性が向上したことでしょう。

絞り込み検索について書かれたサイトはありましたが、(私が見た限り)外部での条件入力に対応したものはありませんでした。そのため、今回筆を取らせていただいた次第です。

今回、私の乏しい知識を総動員し、1つのモデルケースを示しました。初心者がゆえに、他の技術系ブログよりも親切で詳細な内容になっている自負があります。よろしければご自身のサイト運営にご活用ください。

ここまでやれば大物ブロガーと差別化できます。でも、大物ブロガーがこの記事を真似したら?その心配は無用です。弊サイトの記事はそこまでメジャーではありません。そう、この記事を読んだあなたは他の人と差を付けるチャンスなのです!

マイナビ出版 たにぐち まこと
松浦 健一郎、司 ゆき(共著) SBクリエイティブ
スポンサーリンク

シェアする

  • このエントリーをはてなブックマークに追加

フォローする