Extension การสร้างกราฟด้วย HighChart และ Drilldown Chart ใน Yii Framework 2

คู่มือการเรียนรู้ Yii Framework 2 (Yii2)

บทเรียนดีๆ สำหรับผู้ที่ต้องการแบ่งปัน บทเรียนของคุณอาจมีค่าสำหรับอีกหลายๆ คน

beta version

Extension การสร้างกราฟด้วย HighChart และ Drilldown Chart ใน Yii Framework 2

มานพ กองอุ่น yii graph highcharts 4300

สำหรับ HightCharts นั้นเป็นระบบการทำกราฟที่เป็น JavaScript โดยจะทำงานที่ฝั่ง Client ดังนั้น เราจำเป็นจะต้องสร้างข้อมูลจากฐานข้อมูลให้อยู่ในรูปของ JavaScript เพื่อส่งให้ HightCharts แสดงผล แต่สาหรับการจัดการกับ HightCharts ในบทนี้จะสร้างกราฟจาก Yii2 Extension ที่มีคนได้ทำไว้ในรูปแบบของ PHP แล้ว โดยทำการติดตั้งดังนี้

composer require miloschuman/yii2-highcharts-widget

ทั้งนี้สามารถดูรายละเอียดเพิ่มเติมได้ที่เว็บไซต์ 

https://github.com/miloschuman/yii2-highcharts
https://packagist.org/packages/miloschuman/yii2-highcharts-widget

โดยมีตัวอย่างของการเขียนโปรแกรมเพื่อแสดงผลข้อมูลดังนี้
 

use miloschuman\highcharts\Highcharts;

echo Highcharts::widget([
   'options' => [
      'title' => ['text' => 'Fruit Consumption'],
      'xAxis' => [
         'categories' => ['Apples', 'Bananas', 'Oranges']
      ],
      'yAxis' => [
         'title' => ['text' => 'Fruit eaten']
      ],
      'series' => [
         ['name' => 'Jane', 'data' => [1, 0, 4]],
         ['name' => 'John', 'data' => [5, 7, 3]]
      ]
   ]
]);

การเตรียมข้อมูลสำหรับทำกราฟ

สำหรับการเตรียมข้อมูลนั้นเราจะนำข้อมูลที่ได้ไปแสดง 2 ส่วนนั่นคือ ส่วนที่เป็นตาราง GridView และส่วนแสดงผลกราฟ

สร้าง ReportController.php

สร้างไฟล์ Controller สำหรับเก็บ Action ในการดึงข้อมูลมาเตรียมเพื่อส่งให้กับ View โดยสร้างที่ controllers/ReportControlller.php จากนั้นเขียนโปรแกรมเพิ่ม Action Report1() ดังนี้

<?php
namespace app\controllers;
use Yii;
use yii\data\ArrayDataProvider;
use yii\web\Controller;

class ReportController extends Controller{
public function actionReport1(){
        $connection = Yii::$app->db;
        $data = $connection->createCommand('
            SELECT year(t.DATETIME_DISCH) as yy,
            month(t.DATETIME_DISCH) as mm,
            COUNT(t.AN) as cnt
            FROM admission t
            GROUP BY yy,mm
            ORDER BY yy,mm
            ')->queryAll();
        //เตรียมข้อมูลส่งให้กราฟ
        for($i=0;$i<sizeof($data);$i++){
            $yy[] = $data[$i]['yy'];
            $mm[] = $data[$i]['yy'].'-'.$data[$i]['mm'];
            $cnt[] = $data[$i]['cnt'];
        }
        
        $dataProvider = new ArrayDataProvider([
            'allModels'=>$data,
            'sort'=>[
                'attributes'=>['yy','mm','cnt']
            ],
        ]);
        return $this->render('report1',[
            'dataProvider'=>$dataProvider,
            'yy'=>$yy,'mm'=>$mm,'cnt'=>$cnt,
        ]);
    }
}

 

กราฟแท่ง (Column)

สร้าง View เพื่อแสดงผลกราฟ โดยระบุ Property สำหรับการแสดงผลกราฟในรูปแบบกราฟแท่ง หรือ Column โดยมีการกำหนดการแสดงผล 2 ส่วนคือส่วนแสดงกราฟ และส่วนการแสดง Grid View โดยมีรายละเอียดดังนี้


ส่วนแสดงกราฟ

สำหรับส่วนของการแสดงผลแบบกราฟ นั้นมีการเขียนโปรแกรมดังนี้ จะเห็นว่าส่วนที่เน้นตัวหนาคือส่วนที่แสดงผลแบบกราฟแท่ง 'type' => 'column'

views/report/report1.php
<?php
$this->title = 'จำนวนผู้ป่วยในแยกรายเดือน';
$this->params['breadcrumbs'][] = $this->title;
use yii\grid\GridView;
use miloschuman\highcharts\Highcharts;
?>
<!-- ส่วนแสดงกราฟ -->
<div class="panel panel-info">
    <div class="panel-heading">
        <h3 class="panel-title">
            <i class="glyphicon glyphicon-signal"></i>
            จำนวนผู้ป่วยในแยกรายเดือน</h3>
    </div>
    <div class="panel-body">
        <?php
        echo Highcharts::widget([
            'options' => [
                'title' => ['text' => 'จำนวนผู้ป่วยในแยกรายเดือน'],
                'xAxis' => [
                    'categories' => $mm
                ],
                'yAxis' => [
                    'title' => ['text' => 'จำนวน(คน)']
                ],
                'series' => [
                    [
                        'type' => 'column',
                        'name' => 'CNT',
                        'data' => $cnt,
                    ]
                ]
            ]
        ]);
        ?>
    </div>
</div>

ส่วนแสดง Grid View

ส่วนของ Grid View เป็นส่วนแสดงผลข้อมูลเป็นตาราง โดยมีการกำหนดรายละเอียดให้สามารถเรียงลำดับข้อมูลในคอลัมน์ได้ดังนี้

<!-- ส่วนแสดง Grid View -->
<div class="panel panel-danger">
    <div class="panel-heading">
        <h3 class="panel-title"><i class="glyphicon glyphicon-signal"></i> จำนวนผู้ป่วยในแยกรายเดือน</h3>
    </div>
    <div class="panel-body">
        <?php
        echo GridView::widget([
            'dataProvider' => $dataProvider,
            'columns' => [
                ['class' => 'yii\grid\SerialColumn'],
                [
                    'label' => 'ปี',
                    'attribute' => 'yy'
                ],
                [
                    'label' => 'เดือน',
                    'attribute' => 'mm'
                ],
                [
                    'label' => 'จำนวนผู้ป่วยใน',
                    'attribute' => 'cnt'
                ],
            ]
        ]);
        ?>
    </div>
</div>


ตัวอย่างการแสดงผลกราฟ
ตัวอย่างการแสดงผล Grid View

 

กราฟเส้น (Line)

สร้าง view เพื่อแสดงผลกราฟ ด้านล่างของ gridview ของส่วนกราฟแท่ง เพื่อทดสอบ

views/report/report1.php

ส่วนแสดงกราฟ

ส่วนของการแสดงกราฟจะเรียกใช้ Highcharts และกำหนดลักษณะการแสดง 'type' => 'line' ซึ่งจะแสดงผลออกมาเป็นกราฟเส้น

<?php
$this->title = 'จำนวนผู้ป่วยในแยกรายเดือน';
$this->params['breadcrumbs'][] = $this->title;
use yii\grid\GridView;
use miloschuman\highcharts\Highcharts;
?>
<!-- ส่วนแสดงกราฟ -->
<div class="panel panel-info">
    <div class="panel-heading">
        <h3 class="panel-title">
            <i class="glyphicon glyphicon-signal"></i>
            จำนวนผู้ป่วยในแยกรายเดือน</h3>
    </div>
    <div class="panel-body">
        <?php
        echo Highcharts::widget([
            'options' => [
                'title' => ['text' => 'จำนวนผู้ป่วยในแยกรายเดือน'],
                'xAxis' => [
                    'categories' => $mm
                ],
                'yAxis' => [
                    'title' => ['text' => 'จำนวน(คน)']
                ],
                'series' => [
                    [
                        'type' => 'line',
                        'name' => 'CNT',
                        'data' => $cnt,
                    ]
                ]
            ]
        ]);
        ?>
    </div>
</div>


ส่วนแสดง Grid View

<!-- ส่วนแสดง Grid View -->
<div class="panel panel-danger">
    <div class="panel-heading">
        <h3 class="panel-title"><i class="glyphicon glyphicon-signal"></i> จำนวนผู้ป่วยในแยกรายเดือน</h3>
    </div>
    <div class="panel-body">
        <?php
        echo GridView::widget([
            'dataProvider' => $dataProvider,
            'columns' => [
                ['class' => 'yii\grid\SerialColumn'],
                [
                    'label' => 'ปี',
                    'attribute' => 'yy'
                ],
                [
                    'label' => 'เดือน',
                    'attribute' => 'mm'
                ],
                [
                    'label' => 'จำนวนผู้ป่วยใน',
                    'attribute' => 'cnt'
                ],
            ]
        ]);
        ?>
    </div>
</div>


ตัวอย่างการแสดงกราฟ


 
ตัวอย่างการแสดง Grid View

 

การสร้าง Drilldown Chart

Drilldown เป็นการแสดงผล Chart ที่สามารถคลิกดูรายละเอียดจาก Chart หลักได้ เช่น จากกราฟที่เราได้ทำมาแสดงผลเป็นรายเดือน หากเราต้องการทราบว่าแต่ละวันในเดือนนั้นมีการเกิดอุบัติเหตุเท่าไรเราก็คลิกไปที่กราฟแต่ละแท่งก็จะแสดงกราฟย่อยให้เห็นเป็นรายวันนั่นเอง

ตัวอย่าง Code ในการทำ Drilldown

โดยใน Chart หลักจะส่งหมายเลข (number) ไปเพื่อเป็นคีย์อ้างอิงในการเรียก Drilldown สังเกตที่ 'drilldown' => $r['number'] อย่าลืมใส่ intval() สำหรับค่าที่เป็นตัวเลขใน Chart

สำหรับค่าที่จะใส่ใน Drilldown นั้นอยู่ใน $sub[] ซึ่งเป็น Array ที่เป็น Set ของข้อมูลโดยต้องมี 3 key ดังต่อไปนี้ id, name และ data 

  • id คือคีย์ที่จะถูกส่งมาจาก Chart หลัก
  • name คือ Label ที่จะแสดงผล
  • data คือค่าของข้อมูลที่จะแสดงใน Chart

ดูรายละเอียดของ ReportController ใน actionIndex() ดังต่อไปนี้

<?php

namespace frontend\modules\borrow\controllers;
use yii\data\ArrayDataProvider;
use Yii;

class ReportController extends \yii\web\Controller
{
    public function actionIndex()
    {
        $sql = "SELECT COUNT(bi.id) as total,n.number FROM borrow_item bi
            LEFT JOIN number_sim nm ON nm.id = bi.number_sim_id
            LEFT JOIN number n ON n.id = nm.number_id
            GROUP BY bi.number_sim_id
               ";
        $rows = Yii::$app->db->createCommand($sql)->queryAll();
        $graph = [];
        foreach($rows as $r){
            $graph[] = [
                //'type' => 'column',
                'name' => $r['number'],
                'y' => intval($r['total']),
                'drilldown' => $r['number'],
            ];
        }

        $y = date('Y');

        $sql_sub = "SELECT n.number,
        COUNT(IF(MONTH(date_out)=1,bi.id,NULL)) AS m1,
        COUNT(IF(MONTH(date_out)=2,bi.id,NULL)) AS m2,
        COUNT(IF(MONTH(date_out)=3,bi.id,NULL)) AS m3,
        COUNT(IF(MONTH(date_out)=4,bi.id,NULL)) AS m4,
        COUNT(IF(MONTH(date_out)=5,bi.id,NULL)) AS m5,
        COUNT(IF(MONTH(date_out)=6,bi.id,NULL)) AS m6,
        COUNT(IF(MONTH(date_out)=7,bi.id,NULL)) AS m7,
        COUNT(IF(MONTH(date_out)=8,bi.id,NULL)) AS m8,
        COUNT(IF(MONTH(date_out)=9,bi.id,NULL)) AS m9,
        COUNT(IF(MONTH(date_out)=10,bi.id,NULL)) AS m10,
        COUNT(IF(MONTH(date_out)=11,bi.id,NULL)) AS m11,
        COUNT(IF(MONTH(date_out)=12,bi.id,NULL)) AS m12
        FROM borrow_item bi
        LEFT JOIN borrow b ON b.id = bi.borrow_id
        LEFT JOIN number_sim ns ON ns.id = bi.number_sim_id
        LEFT JOIN number n ON n.id = ns.number_id
        WHERE YEAR(date_out) = '$y'
        GROUP BY bi.number_sim_id";

        $row_sub = Yii::$app->db->createCommand($sql_sub)->queryAll();
        $sub = [];
        foreach($row_sub as $rs){
            $sub[] = [
                //'type' => 'column',
                'id' => $rs['number'],
                'name' => $rs['number'],
                'data' => [['ม.ค.', intval($rs['m1'])], ['ก.พ.', intval($rs['m2'])], ['มี.ค.', intval($rs['m3'])], ['เม.ย.', intval($rs['m4'])], ['พ.ค.', intval($rs['m5'])], ['มิ.ย.', intval($rs['m6'])], ['ก.ค.', intval($rs['m7'])], ['ส.ค.', intval($rs['m8'])], ['ก.ย.', intval($rs['m9'])], ['ต.ค.', intval($rs['m10'])], ['พ.ย.', intval($rs['m11'])], ['ธ.ค.', intval($rs['m12'])]]
            ];
        }

        $dataProvider = new ArrayDataProvider([
            'allModels' => $rows,
            'sort' => [
                'attributes' => [

                ]
            ]
        ]);
        return $this->render('index',[
            'graph' => $graph,
            'drilldown' => $sub,
            'dataProvider' => $dataProvider,
        ]);
    }


}

ตัวอย่างไฟล์ views/report/index.php

สำหรับการแสดงผลในไฟล์ view เราจะตั้งค่าการแสดงผลดังนี้

<?php
use miloschuman\highcharts\Highcharts;
?>
<div class="box box-warning box-solid">
    <div class="box-header with-border">
        <h3 class="box-title">Report1</h3>
    </div>
    <!-- /.box-header -->
    <div class="box-body">
        <?=Highcharts::widget([
            'id' => 'chart1',
            'scripts' => [
                'highcharts-more',
                'highcharts-3d',
                'modules/drilldown',
            ],
            'options' => [
                'credits' => ['enabled' => false],
                'type' => 'column',
                
                
            ]
         ])?>
        <div id="chart1"></div>
    </div>
</div>

<?php $this->registerJs("$(function () {
    // Create the chart
    $('#chart1').highcharts({
        chart: {
            type: 'column'
        },
        title: {
            text: 'กราฟสรุปหมายเลขที่มีการยืม'
        },
        subtitle: {
            text: 'กราฟแสดงข้อมูลสรุปหมายเลขที่มีการยืม'
        },
        xAxis: {
            type: 'category'
        },
        yAxis: {
            title: {
                text: 'จำนวนครั้ง'
            }

        },
        legend: {
            enabled: false
        },
        plotOptions: {
            series: {
                borderWidth: 0,
                dataLabels: {
                    enabled: true,
                    format: '{point.y} ครั้ง'
                }
            }
        },

        tooltip: {
            headerFormat: '<span style=\"font-size:11px\">{series.name}</span><br>',
            pointFormat: '<span style=\"color:{point.color}\">{point.name}</span>: <b>{point.y} ครั้ง</b> <br/>'
        },

        series: [{
            name: 'หมายเลข',
            colorByPoint: true,
            data: ".json_encode($graph)." 
        }],
        drilldown: {
            series: ".json_encode($drilldown)." 
        }
    });
});");

ตัวอย่างการแสดงผล

Chart หลัก

Drilldown Chart

 

หากบทเรียนรู้มีความผิดพลาดประการใด หรือมีข้อเสนอแนะกรุณาแจ้ง contact@programmerthailand.com
กลับขึ้นบน