生活の跡

個人的な備忘録

FuelPHPでDBのデータから作った図表を表示する

概要

DBのデータから図表を作成して表示するWebページを、FuelPHPで作成しました。自分用のメモとして記事に残します。

前提知識

  • FuelPHPにおけるMVCの基本操作
  • SQL、html、javaScriptの基礎
  • JSON形式

環境

  • フレームワーク:FuelPHP 1.8.2
  • DB:MySQL(MAMP)
  • サーバ側の言語:PHP 7.2.1
  • フロント側の言語:html, css, javaScript(jQuery)
  • グラフ描画用ライブラリ:chart.js 2.8.0

大まかな処理の流れ

  1. コントローラにて、モデルから取得したDBデータをビューに渡す
  2. ビューにてscriptタグの属性としてDBデータを保持し、外部ファイル(.js)を呼び出す
  3. 外部ファイル(.js)にて図を作成し、canvas要素に描画する

詳細な手順

1. コントローラにて、モデルから取得したDBデータをビューに渡す

図表に示すデータとして、次のようなレコードを products テーブルに用意しました。

f:id:ishii-akihiro:20191021150906p:plain

モデルとコントローラの内容は次の通りです。

  • モデル
    APPPATH/classes/model/product.php
<?php

class Model_Product extends Model
{
  public static function select_products()
  {
    //DBから製品情報を取得
    $rst = DB::select()->from('products')->execute()->as_array();
    
    return $rst;
  }
}
  • コントローラ
    APPPATH/classes/controller/home.php
<?php

class Controller_Home extends Controller
{
  public function action_index()
  {
    //モデルから製品情報を取得
    $products = Model_Product::select_products();
    
    //ビューを作成
    $view = View::forge('index');
    $view->set('products', $products);
    return $view;
  }
}

2. ビューにてscriptタグの属性としてDBデータを保持し、外部ファイル(.js)を呼び出す

コントローラから渡されたDBデータは$productに格納されており、表にはそのまま使用します。
一方、図はjavaScriptで作成するため、$productのデータを外部ファイル(main.js)に渡す必要があります。bodyタグの最後で外部ファイルを呼び出す際に、そのscriptタグを特定するidと、データを格納した属性を付与します。
ただし、scriptタグの属性に付与するためには、データを配列から文字列に変換する必要があります。javaScriptで再び配列にしやすくするため、JSON形式にしておきます。
外部ファイル(main.js)の他に、jQueryとchart.jsを呼び出しています。今回はいずれもCDNを参照することにしています。

  • ビュー
    APPPATH/views/index.php
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>商品情報</title>
  <?php echo Asset::css('style.css'); ?>
</head>
<body>
  <!-- DB情報を表に示す -->
  <section>
    <h2></h2>
    <table>
      <thead>
        <tr>
          <th>商品名</th>
          <th>値段(円)</th>
        </tr>
      </thead>
      <tbody>
        <?php foreach($products as $key => $val): ?>
          <tr>
            <td><?php echo $val['name']; ?></td>
            <td><?php echo $val['price']; ?></td>
          </tr>
        <?php endforeach; ?>
      </tbody>
    </table>
  </section>
  
  <!-- DB情報を図に示す -->
  <section>
    <h2></h2>
    <div class="canvas-wrapper">
      <canvas id="price"></canvas>      
    </div>
  </section>
  
  <!-- jQuery cdn -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <!-- chart.js cdn -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
  <!-- 自作スクリプトファイル -->
  <?php echo Asset::js('main.js', array('id'=>'script_id','products'=>json_encode($products))); ?>  
</body>
</html>

3. 外部ファイル(.js)にて図を作成し、canvas要素に描画する

ビューの最後に記載したscriptタグを指定し、属性に保持したデータを取得します。
文字列から配列に変換し、図に示すラベルとデータをそれぞれ別の配列に格納します。今回は、ラベルには商品名を、データには値段を使います。下記のコードで、ラベル用のnamesには["にんじん", "レタス", "いちご", "ぶどう"]が、データ用のpricesには[100, 200, 600, 400]が格納されます。

  • javaScript
    public/assets/js/main.js
$(function(){
  //ビューからjson形式の文字列を取得
  $script_tag = $('#script_id');  
  var json_string = $script_tag.attr('products');
  
  //配列に変換
  var json_array = JSON.parse(json_string);
  
  //グラフに使用するデータを抽出した配列を作成
  var names = [];
  var prices = [];
  $.each(json_array, function(index, val){
    names.push(val['name']);
    prices.push(val['price']);
  })
  
  // canvas にグラフを表示
  var ctx = document.getElementById('price').getContext('2d');
  var chart_line = new Chart(ctx, {
    type: 'bar',
    data: {
      labels: names,
      datasets: [
        {
          label: '値段(円)',
          data: prices
        }
      ]
    },
    options: {
      scales: {
        yAxes: [{
          ticks: {
            min: 0,
            max: 1000
          }
        }]        
      }
    }
  });
});

結果

こんな感じで描画できました(cssの内容は省略します)。

f:id:ishii-akihiro:20191021153229p:plain

おわりに

やっとExcelに追いついた気がする。。データから作るならExcelの方が早いけど、用意されたデータを使い回すならWeb技術も活用できるのではなかろうか。

参考

こちらの記事のおかげで流れがわかりました。 phpから外部のjsに値渡し - Qiita

chart.js の棒グラフに関するドキュメントはこちらです。 Bar · Chart.js documentation