プログラミング

【コードDL可】phpで検索機能を作る方法を説明します【2019年版】

更新情報

2018/12/17:一部文字化けを修正しました(しののめさんご報告ありがとうございます!)

 

phpを独学で勉強している人
phpを独学で勉強している人
 最近phpを独学で勉強していて構文は覚えてきた。でも、検索機能でかれこれ3時間は詰まってる・・・。誰か動くものを公開してないかな・・・。

 

ということで、今回はphpで検索機能を作る方法をコードと共に説明したいと思います。

この記事でわかること
  • phpで検索機能を作る方法
  • phpでMySQLサーバのデータを取得する方法
  • phpでHTMLの要素を生成する方法

完成形のコードはこちら

動く状態になっているコードをGitHubに公開しています。よろしければお使いください。
https://github.com/szk-o-i/search-sample

検索機能のデモ画面

今回は、会員のデータを検索する機能を作って行きます。

検索フォーム

検索フォームdemo

名前性別年齢で検索が出来ます。

名前:自由入力

性別:男性、女性

年齢:10代、20代、30代

検索結果がある場合

「◯件見つかりました。」という表記と共に検索結果が表示されます。

検索結果がない場合

「検索対象」は見つかりませんでした。という文章が表示されます。

具体的なコード作成方法

では、具体的に方法を見て行きましょう。

必要なDBを作る

まずは検索に必要なデータを作成しましょう。
こちらのSQL文をお使いください。


CREATE TABLE `users` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NOT NULL COMMENT '名前',
  `sex` INT UNSIGNED NOT NULL COMMENT '性別\n1:男\n2:女',
  `age` INT UNSIGNED NOT NULL COMMENT '年齢',
  `valid` INT UNSIGNED NOT NULL,
  PRIMARY KEY (`id`));

INSERT INTO `users` (`name`, `sex`, `age`, `valid`) VALUES ('田中太郎', '1', '26', '1');
INSERT INTO `users` (`name`, `sex`, `age`, `valid`) VALUES ('山田花子', '2', '16', '1');
INSERT INTO `users` (`name`, `sex`, `age`, `valid`) VALUES ('高橋正樹', '1', '18', '1');
INSERT INTO `users` (`name`, `sex`, `age`, `valid`) VALUES ('金子優子', '2', '31', '1');
INSERT INTO `users` (`name`, `sex`, `age`, `valid`) VALUES ('吉井佳子', '2', '21', '1');
INSERT INTO `users` (`name`, `sex`, `age`, `valid`) VALUES ('橘勇気', '1', '13', '1');
INSERT INTO `users` (`name`, `sex`, `age`, `valid`) VALUES ('小林隆', '1', '39', '1');
INSERT INTO `users` (`name`, `sex`, `age`, `valid`) VALUES ('影山夏生', '1', '11', '0');
INSERT INTO `users` (`name`, `sex`, `age`, `valid`) VALUES ('加藤裕太', '1', '23', '1');
INSERT INTO `users` (`name`, `sex`, `age`, `valid`) VALUES ('後藤由美', '2', '20', '1');

DBの設定ファイルを作る

DBに接続するために必要な情報をファイルに書きましょう。

※この情報は機密情報です。絶対に外部に漏れないようにしましょう

config/database.php


<?php
//DBの接続情報
$host = "localhost";
$username = "root";
$password = "root";
$dbname = "test";

データを取得する関数を作る

検索されたデータを取得するための関数を作りましょう。SQL文を作るロジックが少し複雑ですが、ここが一番ミソなので頑張りましょう。

model.php


<?php
function getUserData($params){
	//DBの接続情報
	include_once('config/database.php');
	//DBコネクタを生成
	$Mysqli = new mysqli($host, $username, $password, $dbname);
	if ($Mysqli->connect_error) {
			error_log($Mysqli->connect_error);
			exit;
	}
	//入力された検索条件からSQl文を生成
	$where = [];
	if(!empty($params['name'])){
		$where[] = "name like '%{$params['name']}%'";
	}
	if(!empty($params['sex'])){
		$where[] = 'sex = ' . $params['sex'];
	}
	if(!empty($params['age'])){
		$where[] = 'age <= ' . ((int)$params['age'] + 9) . ' AND age <= ' . (int)$params['age'];
	}
	if($where){
		$whereSql = implode(' AND ', $where);
		$sql = 'select * from users where ' . $whereSql ;
	}else{
		$sql = 'select * from users';
	}
	
	//SQL文を実行する
	$UserDataSet = $Mysqli->query($sql);
	//扱いやすい形に変える
	$result = [];
	while($row = $UserDataSet-&gt;fetch_assoc()){
		$result[] = $row;
	}
	return $result;
}

 

検索ページを作る

実際の検索ページを作りましょう。​

詳しく説明して行きますが、とりあえずはこちらのファイルを作成しましょう。ポイントになる所には①、②、③でポイントをつけています。

index.php


<?php 
//①データ取得ロジックを呼び出す
include_once('model.php');
$userData = getUserData($_GET);
?>
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>PHPの検索機能</title>
<link rel="stylesheet" href="style.css">
<!-- Bootstrap読み込み(スタイリングのため) -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
</head>
<body>
<h1 class="col-xs-6 col-xs-offset-3">検索フォーム</h1>
<div class="col-xs-6 col-xs-offset-3 well">

	<?php //②検索フォーム ?>
	<form method="get">
		<div class="form-group">
			<label for="InputName">名前</label>
			<input name="name" class="form-control" id="InputName" value="<?php echo isset($_GET['name']) ? htmlspecialchars($_GET['name']) : '' ?>">
		</div>
		<div class="form-group">
			<label for="InputSex">性別</label>
			<select name="sex" class="form-control" id="InputSex">
				<option value="0" <?php echo empty($_GET['sex']) ? 'selected' : '' ?>>選択しない</option>
				<option value="1" <?php echo isset($_GET['sex']) && $_GET['sex'] == '1' ? 'selected' : '' ?>>男性</option>
				<option value="2" <?php echo isset($_GET['sex']) && $_GET['sex'] == '2' ? 'selected' : '' ?>>女性</option>
			</select>
		</div>
		<div class="form-group">
			<label for="InputAge">年齢</label>
			<select name="age" class="form-control" id="InputAge">
				<option value="0" <?php echo empty($_GET['age']) ? 'selected' : '' ?>>選択しない</option>
				<option value="10" <?php echo isset($_GET['age']) && $_GET['age'] == '10' ? 'selected' : '' ?>>10代</option>
				<option value="20" <?php echo isset($_GET['age']) && $_GET['age'] == '20' ? 'selected' : '' ?>>20代</option>
				<option value="30" <?php echo isset($_GET['age']) && $_GET['age'] == '30' ? 'selected' : '' ?>>30代</option>
			</select>
		</div>
		<button type="submit" class="btn btn-default" name="search">検索</button>
	</form>

</div>
<div class="col-xs-6 col-xs-offset-3">
	<?php //③取得データを表示する ?>
	<?php if(isset($userData) && count($userData)): ?>
		<p class="alert alert-success"><?php echo count($userData) ?>件見つかりました。</p>
		<table class="table">
			<thead>
				<tr>
					<th>名前</th>
					<th>性別</th>
					<th>年齢</th>
				</tr>
			</thead>
			<tbody>
				<?php foreach($userData as $row): ?>
					<tr>
						<td><?php echo htmlspecialchars($row['name']) ?></td>
						<td><?php echo htmlspecialchars($row['sex'] == 1 ? '男性' : '女性') ?></td>
						<td><?php echo htmlspecialchars($row['age']) ?></td>
					</tr>
				<?php endforeach; ?>
			</tbody>
		</table>
	<?php else: ?>
		<p class="alert alert-danger">検索対象は見つかりませんでした。</p>
	<?php endif; ?>

</div>
</body>
</html>

詳しく見て行きましょう。

①データ取得ロジックを呼び出す

先ほどのmodel.phpを読み込んで、DBのデータを取得しましょう。


<?php 
//①データ取得ロジックを呼び出す
include_once('model.php');
$userData = getUserData($_GET);
?>

②検索フォーム

検索用のフォームを作りましょう。

検索された値の復元htmlspecialcharsでエスケープするのがポイントですね。


<?php //②検索フォーム ?>
	<form method="get">
		<div class="form-group">
			<label for="InputName">名前</label>
			<input name="name" class="form-control" id="InputName" value="<?php echo isset($_GET['name']) ? htmlspecialchars($_GET['name']) : '' ?>">
		</div>
		<div class="form-group">
			<label for="InputSex">性別</label>
			<select name="sex" class="form-control" id="InputSex">
				<option value="0" <?php echo empty($_GET['sex']) ? 'selected' : '' ?>>選択しない</option>
				<option value="1" <?php echo isset($_GET['sex']) && $_GET['sex'] == '1' ? 'selected' : '' ?>>男性</option>
				<option value="2" <?php echo isset($_GET['sex']) && $_GET['sex'] == '2' ? 'selected' : '' ?>>女性</option>
			</select>
		</div>
		<div class="form-group">
			<label for="InputAge">年齢</label>
			<select name="age" class="form-control" id="InputAge">
				<option value="0" <?php echo empty($_GET['age']) ? 'selected' : '' ?>>選択しない</option>
				<option value="10" <?php echo isset($_GET['age']) && $_GET['age'] == '10' ? 'selected' : '' ?>>10代</option>
				<option value="20" <?php echo isset($_GET['age']) && $_GET['age'] == '20' ? 'selected' : '' ?>>20代</option>
				<option value="30" <?php echo isset($_GET['age']) && $_GET['age'] == '30' ? 'selected' : '' ?>>30代</option>
			</select>
		</div>
		<button type="submit" class="btn btn-default" name="search">検索</button>
	</form>

③取得データを表示する

検索して取得したデータを表示しましょう。難しいことはないです。

エスケープはしっかりしておきましょう。


<?php //③取得データを表示する
	<?php if(isset($userData) && count($userData)): ?>
		<p class="alert alert-success"><?php echo count($userData) ?>件見つかりました。</p>
		<table class="table">
			<thead>
				<tr>
					<th>名前</th>
					<th>性別</th>
					<th>年齢</th>
				</tr>
			</thead>
			<tbody>
				<?php foreach($userData as $row): ?>
					<tr>
						<td><?php echo htmlspecialchars($row['name']) ?></td>
						<td><?php echo htmlspecialchars($row['sex'] == 1 ? '男性' : '女性') ?></td>
						<td><?php echo htmlspecialchars($row['age']) ?></td>
					</tr>
				<?php endforeach; ?>
			</tbody>
		</table>
	<?php else: ?>
		<p class="alert alert-danger">検索対象は見つかりませんでした。</p>
	<?php endif; ?>

 

注意ポイント

以上で完成となります。ブラウザでindex.phpを開いて検索しましょう。

基本的な検索機能はこんな感じですので、これを応用して色々な検索機能を作って見てくださいね!

いくつかポイントはありますが、まとめると主な注意点としては

注意点3つ
  • SQL文のwhere部分のロジック
  • phpで文字を出力する時のエスケープ
  • DB接続情報の漏えい

の3つかと思います。
特に最後のDB情報が漏れるというのは、誰でもDBに接続できる状態と同義です。検索機能と直接的に関わるものではありませんが、WEBアプリケーションを作る上では注意しましょう。

もし他にわかりづらいところがあれば、ツイッター(@kikiki_kirin) もやっているのでお気軽にご指摘いただけると記事の修正にも活かせるので嬉しいです。

それでは〜

よくある質問

読者の方からツイッターにいただいた質問とその回答を載せておきますのでご参考までに。

Q.「DBに繋がらない」-2019/3/5追記

詳しい状況:「Access denied for user ‘root’@’localhost’」というエラーメッセージが出て検索画面にデータが表示されない。DBを見てみるとデータはちゃんと入っている。

参考画像

対応方法

原因:MySQLに接続しようとしているユーザーのパスワードがないのが原因です。

対応方法:対象ユーザーのパスワードを設定しましょう。または、mysqliクラスを宣言する時の引数パスワードをNULLにしましょう(http://php.net/manual/ja/mysqli.construct.php)。

 

プログラミングの独学に挫折しそうな人へ

教えてくれる人がいると効率が圧倒的に変わります。無料で学べる方法もあるのでお試しください。

プロのエンジニアがすすめるプログラミングスクールは4社だけ【無料あり】「プログラミングを学んでみたいからスクールに行きたいけど数が多すぎてどこに決めれば良いかわからない・・・」 という疑問にお答えして...
ABOUT ME
Avatar
きりん
『好きなだけ漫画を語る。』そう思い立ち『きり漫』を立ち上げました。内容は大好きな漫画やアニメ・海外ドラマのこと。プログラミングもします。 私の発信する情報が皆さんのためになる事を願って記事を書いています。