PHPでDBからSQLでデータを検索して、HTML/CSSでグラフ化

「DBからSQLひっこぬいて数値化/グラフ化みたいな業務は?」と聞かれたので考えてみました。
スクールでPHPでDBからSQLで検索して引っ張り出したデータをHTMLのtableに表示させたり、pCartというライブラリでグラフを作ったりはしましたが、さてさて。


とりあえずPHP自体久しぶりなので、ドットインストールでPHPの基礎(応用編)のデータベースに関する#01~#05を復習。
ドットインストール
スクールではPEAR:MDB2を使ってDBに接続してましたが、ドットインストールではPDOを使っていたので、今回はPDOで。


久しぶりにphpMyAdminにログインして、schoolというデータベースを作成して、studentというテーブルを作成、データNo、名前、科目、点数で項目を作成。
今回作成したtableはこんな感じ。

s_no s_name kamoku tensu
3 佐藤 数学 30
4 鈴木 数学 50
5 田中 数学 40
7 佐藤 国語 40
8 鈴木 国語 20
9 田中 国語 80


まず、phpMyAdminでデータを追加したら、日本語の名前と科目が文字化けしたので、あわてて照合順序をutf8_general_ciに設定しなおす。
これでDB内ではちゃんと日本語が表示されるようになったが、PHPで呼び出したらまだ文字化けするので検索。下記サイトを参考にさせていただきました。
PDOにおける一応の安全宣言と残る問題点


これでとりあえずDBを作成、接続してデータを引っ張り出せるようになりました。今度はそれをグラフ化するにはどうしたらいいのか?
今回はライブラリを使用せず、PHP5とXHTML/CSSだけでやってみることに。
formで科目を選んで送信ボタンをクリックすると、選択した科目の点数が高い順にソートされて表示される縦の棒線グラフを作ることにしました。


ということで、まずはグラフの表示については、今回は下記サイトの「3. 今度はカラフルでカッコいい棒グラフのサンプル。」を使用。
CSSオンリーでクールなグラフを書くサンプル集


点数ということで平均点も表示したいなと思ったので、配列の平均を出すにはどうしたらと検索して、下記ページを参考に。(結論は配列を合計して、配列の個数で割ることに。)
phpの配列処理で、配列を足すのは、array_sumがあると思うのですが、平均値や最大値、最小値を出力するような関数はあるんでしょうか?:人力はてな


平均点を小数点第一位まで表示して、第二位以下を四捨五入したいなと思って、検索した辿り着いたの下記サイトを参考に。(10掛けて10で割るとは。)
離れPHP島:No24.くるくるっと丸めるぞ ----切上げ、切捨て、四捨五入


※後で気付きましたが、データNoの項目を主キー、オートインクリメントにしたのですが、これだとユーザーIDには使えないですね(^_^;)
ユーザーIDとして使う、ユーザごとにデータをまとめるとしたら、科目の項目は不要、科目ごとの点数の項目を作成すればいいのかな。


という訳でコード(index.php)。CSS(table.css)についてはグラフは上記サイトCSSオンリーでクールなグラフを書くサンプル集のをそのままに背景画像の削除と項目数の削減(5から3に)、それにグラフの下に項目名(名前)を表示させるtableの設定を追加しています。

<?php
//文字化け対策
header("Content-Type: text/html; charset=UTF-8");
//送信データの受け取り
$key=$_GET['kamoku'];
$rows="";
$rowsCount="";
//送信ボタンを押した時の処理
if(isset($key)){
	// データベースへの接続
	try{
		$dbh = new PDO('mysql:host=localhost;dbname=school;charset=utf8','データベース接続ID','データベース接続pw');
	} catch(PDOException $e){
		var_dump($e->getMessage());
		exit;
	}
	// 受け取った送信データ(科目名"kamoku")で検索して、点数("tensu")が高い順にソート
	$sql = "select * from STUDENT where kamoku = '$key' order by tensu desc";
	$stmt = $dbh->query($sql);
	// fetchメソッドを使用して、グラフ部分(点数)は$graphsの配列に収納して、高い順に$graphssに項目追加。
	while($graph=$stmt->fetch(PDO::FETCH_ASSOC)){
		$graphs[]=$graph['tensu'];
		$i=count($graphs)-1;
		if($i==0){
			$graphss .= "<li class='critical' style='height:".($graphs[$i]*1.6)."px;'>".$graphs[$i]."</li>";
		}elseif($i==1){
			$graphss .= "<li class='high' style='height:".($graphs[$i]*1.6)."px;'>".$graphs[$i]."</li>";
		}else{
			$graphss .= "<li class='medium' style='height:".($graphs[$i]*1.6)."px;'>".$graphs[$i]."</li>";
		};
                //グラフの下部に個々人の名前をtableで表示(セル幅はcssでグラフと合わせる)
		$rows .= "<td>".$graph['s_name']."</td>";
	};
	//平均点の算出(小数点第一位まで第二位以下は四捨五入)
	$tenCount="平均点は".(round((array_sum($graphs)/count($graphs))*10)/10)."点です。";
	//切断
	$dbh = null;
}else{
	$rowsCount="科目を選んで下さい";
};
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML1.0Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>生徒の点数表</title></head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link href="table.css" rel="stylesheet" type="text/css" />
</head>
<body>
<form action="index.php" method="get">
	科目:<select name="kamoku">
		<option value="国語">国語</option>
		<option value="数学">数学</option>
	</select>
	<input type="submit" value="選択" />
</form>
<h1><?php echo $key; ?></h1>
<div id="vertgraph">
	<ul>
        	<?php echo $graphss; ?>
	</ul>
	<table id="table-01">
	<tr>
		<?php echo $rows; ?>
	</tr>
	</table>
</div>
<p><?php echo $rowsCount; ?></p>
<p style="margin-top:50px;"><?php echo $tenCount; ?></p>
</body>
</html>

画面イメージ