【プログラミング構築】データベースにアクセスして投稿データを抽出しよう

しょごたん


【プログラミング構築】データベースにアクセスして投稿データを抽出しよう

こんにちは、しょごです。
毎晩ファイナルファンタジー14で遊ぶのが日課です。現在FCメンバーを募集しています。オンするメンバーが減っちゃったので、、一緒に夜な夜な楽しめる人募集です。

さて、この連載では簡単な掲示板を構築しながら、バックエンド技術をイチから学んでいきます。

前回は掲示板に入力されたデータをPOST送信でデータベースに登録しました。


 
今回は登録したデータを抽出してみましょう。
登録したデータを抽出することで、自分の思うようにデータを扱う方法も学んでいきたいと思います。

データ抽出の仕組み

データ抽出の仕組みは下記のような形です。

  • データベースにアクセスし、投稿データを取得する
  • 取得したデータを元にデータを並べる

一つずつ作っていきましょう。

データ取得ロジックを用意する

まずは投稿データをデータベースから取得します。

前回用意した、データを保存するロジックのファイルに追記しましょう。今回はデータの読み込みになるので、select文を用いたロジックを仕込みます。

▼class/business/getFormAction.php

class getFormAction {
	public $pdo;

	/**
	 * コネクション確保
	 */
	function __construct() {
		try {
			$this->pdo = new PDO( PDO_DSN, DATABASE_USER, DATABASE_PASSWORD, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
		} catch (PDOException $e) {
			echo 'error' . $e->getMessage();
			die();
		}
	}

	/**
	 * 記事データをDBに保存
	 */
	function saveDbPostData($data){

		// データの保存
		$smt = $this->pdo->prepare('insert into post (name,email,body,created_at,updated_at) values(:name,:email,:body,now(),now())');
		$smt->bindParam(':name',$data['name'], PDO::PARAM_STR);
		$smt->bindParam(':email',$data['email'], PDO::PARAM_STR);
		$smt->bindParam(':body',$data['body'], PDO::PARAM_STR);
		$smt->execute();

	}
	
	// -----------------ここを追記--------------------
	/**
	 * 記事データをDBから読み込み
	 */
	function getDbPostData(){
		// 登録データ取得
		$smt = $this->pdo->prepare('select * from post order by created_at DESC limit 100');
		$smt->execute();
		// 実行結果を配列に返す。
		$result = $smt->fetchAll(PDO::FETCH_ASSOC);

		return $result;
	}	

	
}

今回追記したgetDbPostという関数を利用することで、登録日付の新しいものから100件を取得することができます。

前回、PDOでデータを登録した際はPOSTデータを加える必要があったので、プレースホルダを利用しSQL文を調整しました。しかし今回はPOSTデータを利用しないシンプルなselect文を利用するので、そのまま記述して結果を配列として取得します。

ちなみに、fetchAllにPDO::FETCH_ASSOCを引数で与えることで、データベースのカラム名をkeyとした配列を取得できます。
つけない場合はカラム名に加えてカラムの順番数がkey値に入った同データもついてきちゃいますが、この形にしておくと余計なデータを生成しなくてよいのでこちらで。

これでデータベースから投稿データを抽出する準備ができました。
次に、この関数を投稿一覧画面に組み込みます。

取得した投稿データを元に投稿一覧を成形する

データベースから取得した投稿データは、「配列データ」で取得されています。

データベースのカラム名が取得した配列データのkey値に設定されているので、データをループさせてHTMLを形成します。

配列データとは

配列データはPHPで扱う型の一種で、複数のデータを格納して扱うことができます。
例えると、物が入っている箱が一列に並んでおり、箱の数を指定してその中に入っているデータを出し入れするイメージです。

$array = array("藤崎詩織","虹野沙希","朝比奈夕子","鏡魅羅");

上記は一列に4つ格納できる箱の中にそれぞれのデータが入っている状態です。
最初のデータを取得する場合、phpでは0番目の中身を取得する形になり、

echo $array[0];

と、記述します。
この0番目と指定する部分をkey値と言います。

ひとつずつデータを取得する場合は、key値に0〜4の値を設定してあげれば取得することができます。しかしデータが可変する場合は、配列を一つずつ自動でずらして取得する記述をします。
その際、foreach文を使うと便利です。

$array = array("藤崎詩織","虹野沙希","朝比奈夕子","鏡魅羅");

foreach ($array as $data) {
	echo $data;	
}

foreach文は配列($array)を(as)一つずつ変数($data)に割り当て、全てのデータが終わるまで繰り返し処理をしてくれます。
これを利用すると配列が状況によって可変した場合も全てのデータを抽出できます。

また、例のような1列にデータが並んでいる配列を「一次元配列」といいます。今回の投稿データは、この一次元配列がさらに複数まとまった状態のデータになります。

実際に取得すると下記のような形です。

$post_datas = Array
(
    [0] => Array
        (
            [id] => 1
            [name] => 名前
            [email] => めーるあどれす
            [body] => 本文ないよう
			ないよう
			こちら
            [created_at] => 2016-05-06 17:56:33
            [updated_at] => 2016-05-06 17:56:33
            [deleted_at] => 
        ),
    [1] => Array
        (
            [id] => 1
            [name] => 名前
            [email] => めーるあどれす
            [body] => 本文ないよう
			ないよう
			こちら
            [created_at] => 2016-05-06 17:56:33
            [updated_at] => 2016-05-06 17:56:33
            [deleted_at] => 
        )

)

このように、データの格納されている配列が行をなして複数存在する配列を「二次元配列」といいます。0番目にひとつ目の投稿データ、1番目に2つ目の投稿データという形です。
配列の数が複雑になりましたが、こちらもforeach文を利用することで簡単にデータが取得できます。

実際に用意した投稿画面を構成するファイルを下記のように変更します。

▼view/post.php

<?php

// -----------------ここを追記--------------------
// 登録データ取得
$post_datas = $action->getDbPostData();

?>
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>掲示板やんなー</title>
</head>
<body>
	<h1>掲示板やんなー</h1>
	<!-- 入力エリア -->
	<div class="input_area">
		<form action="./index.php" method="post" id="contact_form">
			<dl class="name">
				<dt>名前</dt>
				<dd><input type="text" name="name" value=""></dd>
			</dl>
			<dl class="email">
				<dt>メールアドレス</dt>
				<dd><input type="text" name="email" value=""></dd>
			</dl>
			<dl class="body">
				<dt>本文</dt>
				<dd><textarea name="body"></textarea></dd>
			</dl>
			<input type="hidden" name="eventId" value="save">
			<input type="submit" value="送信">
		</form>
	</div>
	<!-- //入力エリア -->
	<hr>
	<!-- 投稿表示エリア -->
	<!-- ココから変更-------------------------- -->
	<?php if (!empty($post_datas)) {?>
	<div class="list">
		<?php foreach ($post_datas as $post) { ?>
		<div class="item">
			<div class="name"><?php if (!empty($post["email"])) {?><a href="mailto:<?php echo $post["email"];?>"><?php } ?><?php echo $post["name"];?><?php if (!empty($post["email"])) {?></a><?php } ?></div>
			<div class="body"><?php echo nl2br($post["body"]);?></div>
			<div class="date"><?php echo $post["created_at"];?></div>
		</div>
		<?php } ?>
	</div>
	<?php } ?>
	<!-- // 投稿表示エリア -->
</body>
</html>

先ほど紹介したように投稿データは配列で取得してくるので、foreach文を使ってデータを一つずつ紐解き設置していきます。
また、前々回に提示した仕様にのっとり、メールアドレスが入力されていた場合は名前にmailtoリンクを付与。本文は改行を適用する形にします。

データがなかった場合のことも加味しておくことで、万が一空の配列が渡ってきたとしてもwarning表記が出ないようにしておきます。

これでデータベースに格納したデータを抽出することができました。

おまけ:トランザクションについて

今回はデータの登録と読み込みを簡単な記述で行っていますが、仕様によってはデータの読み書きを行う際にもっと細かい手順が必要です。
例えば一度の登録で複数のデータ更新処理を必要とする場合、この複数の処理を一つの単位にまとめて管理することが可能で、この処理単位をトランザクションといいます。

トランザクションを利用することで、データの取得や計算など全ての処理が成功したときのみデータベースへの変更を有効としたり、何らかの原因によって一部の処理が正しく実行されなかったときに全ての処理をキャンセルし作業自体を取り消したりすることが可能になります。

データ登録や更新時にもトランザクション処理を細かく行うことはできますが、今回は省略しています。

まとめ

これで掲示板の基本動作は作成できたことになりますが、現状だとひたすら投稿してデータを保持するだけになります。
そのため次回は、保存したデータを更新・削除するロジックを設けます。

それでは。

しょごたん
この記事を書いた人
しょごたん

バックエンドエンジニア

関連記事