Table: exams テーブル
| id | user_id | math | english | physics |
| 1 | 1 | 49 | 36 | 56 |
| 2 | 2 | 45 | 48 | 42 |
| 3 | 3 | 72 | 80 | 91 |
function exam_total() {
$users = $this->User->find('all');
foreach ($users as $user) {
$total[$user['User']['id']] = 0;
$total[$user['User']['id']] = $user['Exam']['math'] + $user['Exam']['english'] + $user['Exam']['physics'];
}
$this->set('users', $users);
$this->set('total', $total);
$this->set('graph_path', './exam_total_graph');
}
function exam_total_graph() {
/* JpGraph を使用する */
App::import('Vendor', 'jpgraph/jpgraph');
App::import('Vendor', 'jpgraph/jpgraph_bar');
/* DB から値を取得 */
$users = $this->User->find('all');
$y1data = array();
$y2data = array();
$zerodata = array();
$a = array();
/* 合計計算 */
foreach ($users as $user) {
$total = 0;
$total = $user['Exam']['math'] + $user['Exam']['english'] + $user['Exam']['physics'];
array_push($y1data, $user['Exam']['math']);
array_push($y2data, $total);
array_push($zerodata, 0);
array_push($a, $user['User']['username']);
}
/* グラフ作成 */
$graph = new Graph(350, 250, "auto");
$graph->SetScale("textlin", 0, 100);
$graph->SetY2Scale("lin", 0, 300);
/* 右側の Y 軸で値が全部表示できないのでグラフを表示する場所の
* margin を指定する
*/
$graph->img->SetMargin(30, 30, 30, 30);
/* X軸項目追加 */
$graph->xaxis->SetTickLabels($a);
/* plot作成 */
$bplot1 = new BarPlot($y1data);
$bplot1->value->Show();
$bplot1->value->SetFormat('%d');
$bplot2 = new BarPlot($y2data);
$bplot2->value->Show();
$bplot2->value->SetFormat('%d');
/* 単純に bplot1, bplot2 を表示するとグラフが重なってしまうので
* $zerodata のダミーを間に挟んでグループ化して
* bplot1, bplot2 が並んでいるように表示する
*/
$bplotzero = new BarPlot($zerodata);
$bgplot1 = new GroupBarPlot(array($bplot1, $bplotzero));
$bgplot2 = new GroupBarPlot(array($bplotzero, $bplot2));
/* グラフ上に描画 */
$graph->Add($bgplot1);
$graph->AddY2($bgplot2);
/* グラフ表示 */
$graph->Stroke();
}
この中で DB にアクセスして値を格納し、各人の合計得点を計算する箇所が重複している
$users = $this->User->find('all');
foreach ($users as $user) {
$total[$user['User']['id']] = 0;
$total[$user['User']['id']] = $user['Exam']['math'] + $user['Exam']['english'] + $user['Exam']['physics'];
}
Cache 機能を使うことで DB へのアクセスを減らすことが可能となる。
Cache::read($key, $config = null); Cache::write($key, $value, $config = null); Cache::delete($key, $config = null);
- write() で $key に入力した文字列に $value の値を関連付けて保存する。
- read() で $key に関連付けられた値を読み込む。
- delete() で $key の値を cache から削除する。
function exam_total() {
$users = $this->User->find('all');
foreach ($users as $user) {
$total[$user['User']['id']] = 0;
$total[$user['User']['id']] = $user['Exam']['math'] + $user['Exam']['english'] + $user['Exam']['physics'];
}
$this->set('users', $users);
$this->set('total', $total);
Cache::write('users', $users);
Cache::write('total', $total);
}
function exam_total_graph() {
/* JpGraph を使用する */
App::import('Vendor', 'jpgraph/jpgraph');
App::import('Vendor', 'jpgraph/jpgraph_bar');
/* Cache に保存された値を読み込む */
$users = Cache::read('users');
$total = Cache::read('total');
Cache::delete('users');
Cache::delete('total');
$y1data = array();
$y2data = array();
$zerodata = array();
$a = array();
foreach ($users as $user) {
array_push($y1data, $user['Exam']['math']);
array_push($y2data, $total[$user['User']['id']]);
array_push($zerodata, 0);
array_push($a, $user['User']['username']);
}
(以下略)
- exam_total() の最後で $users, $total を Cache に保存しておき、exam_total() の後に呼び出される exam_total_graph() では cache のデータを利用するように変更して DB へのアクセス回数を減らすことができる。
- Cache::write() により app/tmp/cache 以下に cake_total, cake_users というファイルが生成される。これを exam_total_graph() 関数で Cache::read() により読み出し、読み出し後は Cache::delete() で削除する。
0 件のコメント:
コメントを投稿