Yii Framework2 กับ VueJS เรียก JSON ด้วย Axios

wave
มานพ กองอุ่น 10 เม.ย. 2018 12:09:40 11,176

ในบทความนี้เป็นแนวทางในการนำ VueJS มาใช้ร่วมกันกับ Yii Framework 2 ในการโหลดข้อมูล API / JSON มาแสดงผลด้วย Axios โดยไม่ได้ Refresh หน้าเว็บ (คุณสมบัติเด่นเขาล่ะ one page application)

Package ที่จะใช้มี 3 ตัวคือ

  1. VueJS ตัวพระเอก
  2. Axios ตัวนางเอก
  3. NProgress เอาไวดู progress การโหลดข้อมูล (พระรอง)

หน้าตาก็จะประมาณนี้

เรียก Package ที่เกี่ยวข้อง

เอาละเริ่มกันเลยครับ โดยเริ่มจากการนำ package เข้ามาใส่ใน frontend/views/layouts/main.php เนื่องจากเราไม่ได้ใช้งานแบบ NodeJS ก็เรียกมาใช้แบบนี้ล่ะ

<?php $this->registerJsFile("//cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js", ['position' => \yii\web\View::POS_HEAD])?>
<?php $this->registerJsFile("//unpkg.com/axios/dist/axios.min.js", ['position' => \yii\web\View::POS_HEAD])?>
<?php $this->registerCssFile("https://cdn.rawgit.com/rikmms/progress-bar-4-axios/0a3acf92/dist/nprogress.css")?>
<?php $this->registerJsFile("https://cdn.rawgit.com/rikmms/progress-bar-4-axios/0a3acf92/dist/index.js", ['position' => \yii\web\View::POS_HEAD])?>

POS_HEAD เอาไว้บนหัวเลยเพราะไม่ต้อง load jQuery ก่อน (ไม่เกี่ยวกัน)

เขียน Action ให้ Response JSON

ในที่นี้จะสร้าง Controller action ใหม่ เพื่อให้ response JSON (ยังไม่ได้ทำ API นะ)

<?php

namespace frontend\modules\information\controllers;


use Yii;
use yii\web\Controller;
use yii\web\Response;

class ReportJsonController extends Controller
{
    public function actionAverageGrade()
    {
        Yii::$app->response->format = Response::FORMAT_JSON;

        $data = [];
        $dataProvider = [];
        if(Yii::$app->request->get()){
            $model = Yii::$app->request->get();
            $sql = "
            SELECT 
            MIN(c.ClassName) AS ClassName,
            COUNT(CASE WHEN (CONVERT(float,GPA) < 1) THEN PersonID ELSE NULL END) AS cnt1,
            COUNT(CASE WHEN (CONVERT(float,GPA) BETWEEN 1.00 AND 1.49) THEN PersonID ELSE NULL END) AS cnt2,
            COUNT(CASE WHEN (CONVERT(float,GPA) BETWEEN 1.50 AND 1.99) THEN PersonID ELSE NULL END) AS cnt3,
            COUNT(CASE WHEN (CONVERT(float,GPA) BETWEEN 2.00 AND 2.49) THEN PersonID ELSE NULL END) AS cnt4,
            COUNT(CASE WHEN (CONVERT(float,GPA) BETWEEN 2.50 AND 2.99) THEN PersonID ELSE NULL END) AS cnt5,
            COUNT(CASE WHEN (CONVERT(float,GPA) BETWEEN 3.00 AND 3.49) THEN PersonID ELSE NULL END) AS cnt6,
            COUNT(CASE WHEN (CONVERT(float,GPA) BETWEEN 3.50 AND 3.99) THEN PersonID ELSE NULL END) AS cnt7,
            COUNT(CASE WHEN (CONVERT(float,GPA) = 4.00) THEN PersonID ELSE NULL END) AS cnt8
            
            FROM VRegGPATermClass gpa
            LEFT JOIN RegBClass c ON c.ClassID = gpa.ClassID
            WHERE gpa.CurriculumID = :CurriculumID
            AND AcademicYear = :AcademicYear
            AND TermID = :TermID
            GROUP BY c.ClassID
            ORDER BY c.ClassID
            ";
            $c = Yii::$app->db->createCommand($sql);
            $c->bindValues([
                'CurriculumID' => $model['CurriculumID'],
                'AcademicYear' => $model['AcademicYear'],
                'TermID' => $model['TermID']
            ]);
            $data = $c->queryAll();
            return $data;

        }

    }
}

หน้าตา JSON ก็จะประมาณนี้

[{"ClassName":"มัธยมศึกษาปีที่ 1","cnt1":"1","cnt2":"6","cnt3":"49","cnt4":"48","cnt5":"55","cnt6":"45","cnt7":"1","cnt8":"0"},{"ClassName":"มัธยมศึกษาปีที่ 2","cnt1":"2","cnt2":"12","cnt3":"53","cnt4":"63","cnt5":"49","cnt6":"34","cnt7":"10","cnt8":"0"},{"ClassName":"มัธยมศึกษาปีที่ 3","cnt1":"0","cnt2":"2","cnt3":"52","cnt4":"55","cnt5":"33","cnt6":"47","cnt7":"20","cnt8":"0"}]

 

สร้าง Model สำหรับรับข้อมูล

<?php
/**
 * User: Manop Kongoon
 * Date: 4/7/2018
 * Time: 10:44 PM
 */
namespace frontend\modules\information\models;

class InformationForm extends \yii\base\Model
{
    public $AcademicYear;
    public $CurriculumID;
    public $TermID;
    public $ClassID;

    public function rules()
    {
        return [
            [['AcademicYear', 'CurriculumID', 'ClassID', 'TermID'], 'required'],
        ];
    }

    public function scenarios() {
        $scenarios = parent::scenarios();
        $scenarios['average_grade'] = ['AcademicYear','CurriculumID', 'TermID'];
        $scenarios['summary_class'] = ['AcademicYear','ClassID', 'TermID'];
        return $scenarios;
    }

    public function attributeLabels()
    {
        return [
            'AcademicYear' => 'ปีการศึกษา',
            'CurriculumID' => 'ระดับการศึกษา',
            'TermID' => 'เทอม',
            'ClassID' => 'ชั้น'
        ];
    }
}

เขียนการแสดงผลข้อมูล

<?php

namespace frontend\modules\information\controllers;

use frontend\modules\information\models\InformationForm;
use Yii;

class ReportController extends \yii\web\Controller
{
    public function actionAverageGrade()
    {
        $model = new InformationForm(['scenario' => 'average_grade']);

        if($model->load(Yii::$app->request->post())){
            
        }
        return $this->render('average-grade', [
            'model' => $model
        ]);
    }

   

}

views average-grade.php

<?php

use common\models\RegBCurriculum;
use common\models\RegBTerm;
use yii\grid\GridView;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\Url;
use yii\widgets\ActiveForm;

$this->title = 'ผลการเรียนเฉลี่ย';
?>
<?php $this->registerCss("
    @media only screen and (min-width : 768px) {
        .search {
            display: flex;
            align-items: center;
        }
    }
        ") ?>
<div id="app">
    <div class="panel">

        <div class="panel-body">
            <h3 class="title-hero">
                <?= $this->title ?>
            </h3>
            <?php $form = ActiveForm::begin() ?>


            <div class="row">
                <div class="search">
                <div class="col-md-2"><?= $form->field($model, 'AcademicYear')->textInput(['v-model' => 'AcademicYear']) ?></div>
                <div class="col-md-2"><?= $form->field($model, 'CurriculumID')->dropDownList(ArrayHelper::map(RegBCurriculum::find()->all(), 'CurriculumID', 'CurriculumName'), ['v-model' => 'CurriculumID']) ?></div>
                <div class="col-md-2"><?= $form->field($model, 'TermID')->dropDownList(ArrayHelper::map(RegBTerm::find()->all(), 'TermID', 'TermName'), ['v-model' => 'TermID']) ?></div>
                <div class="col-md-2"><?= Html::button('แสดงผล', ['class' => 'btn btn-success btn-submit', 'v-on:click' => 'report']) ?></div>
                </div>
            </div>

           
            <?php ActiveForm::end() ?>
        </div>


        <table class="table table-bordered table-striped">
            <thead>
            <tr>
                <th>ระดับ</th>
                <th>0.00-0.99</th>
                <th>1.00-1.49</th>
                <th>1.50-1.99</th>
                <th>2.00-2.49</th>
                <th>2.50-2.99</th>
                <th>3.00-3.49</th>
                <th>3.50-3.99</th>
                <th>4.00</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="data in Results">
                <td>{{ data.ClassName }}</td>
                <td>{{ data.cnt1 }}</td>
                <td>{{ data.cnt2 }}</td>
                <td>{{ data.cnt3 }}</td>
                <td>{{ data.cnt4 }}</td>
                <td>{{ data.cnt5 }}</td>
                <td>{{ data.cnt6 }}</td>
                <td>{{ data.cnt7 }}</td>
                <td>{{ data.cnt8 }}</td>
            </tr>
            </tbody>
        </table>
    </div>
</div><!-- app -->

<script>
    loadProgressBar()

    app = new Vue({
        el: "#app",
        data: {
            AcademicYear: "",
            TermID: "",
            CurriculumID: "",
            Results: []
        },
        methods: {
            report: function (event) {
                var vm = this;
                axios.get("<?=Url::to(['/information/report-json/average-grade', true])?>", {
                    params: {
                        AcademicYear: vm.AcademicYear,
                        CurriculumID: vm.CurriculumID,
                        TermID: vm.TermID
                    }
                })
                    .then(function (response) {
                        vm.Results = response.data
                        //console.log(response);
                    })
                    .catch(function (error) {
                        console.log(error);
                    })
            }
        }
    })

</script>

concept คือ มีตัวแปรหลัก 3 ตัว (v-model) คือ ปีการศึกษา, ระดับ และ เทอม ใน input และ dropdownlist

เมื่อกดปุ่ม axios จะส่งข้อมูลแบบ get ไปพร้อมกับตัวแปร ปีการศึกษา, ระดับ, เทอม ไปประมวลผลตาม url ที่กำหนด แล้วตอบกลับเป็น JSON จากนั้นนำ reponse.data มากำหนดค่าให้กับ vm.Results (vm คือ this)

จากนั้นตรงตาราง data in Results ก็เอามา loop (จริงๆ ถ้าใช้ grid component ก็น่าจะดีกว่า) ด้วย v-for


ความคิดเห็น

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

เขียนบทเรียนรู้ของคุณ

รายละเอียด
  • ดู 11,176
  • รักเลย 0
  • หมวดหมู่ Yii Framework 2 (Yii2)
  • เขียนเมื่อ
  • แก้ไขเมื่อ
  • Tags yii2 yii framework2 vuejs axios json
ข้อมูลผู้เขียน
มานพ กองอุ่น

มานพ กองอุ่น

เป็นสมาชิกเมื่อ: 18 ธ.ค. 2009

เนื้อหาที่เกี่ยวข้อง