timezone

การบันทึกเวลาเป็น init นั้นมีข้อดีคือ เราสามารถที่จะเปลี่ยนค่า Time ที่เราบันทีกเป็น TimeZone ที่ใหนก็ได้ ทำให้เรารู้ว่า ณ ช่วงเวลาที่เราบันทึกข้อมูลตอนนี้ เป็นเวลากี่โมง ณ อีก timezone นึง

ตัวอย่างเช่นเรามีระบบ application ที่มีคนใช้อยู่คนละ timeZone เช่น America/Los_Angeles กับ Asia/Bangkok

Yii 2 เราสามารถตั้งค่า default TimeZone ได้ที่ config/main.php ในส่วนของ timeZone ได้

[
    'timeZone' => 'America/Los_Angeles',
    // ...
]

หากไม่รู้ว่า default ของเราเป็น timezone อะไร สามารถใช้ function date_default_timezone_set() เพื่อ echo ตรวจสอบข้อมูลได้ เพราะการแสดงผลจะอิงตาม TimeZone

ส่วนใหญ่ในการสร้างตารางต่างๆ เราก็มักจะมีฟิวด์ที่เก็บข้อมูลคือ

  • create_date บอกว่าเราสร้าง record นี้เมื่อไหร่
  • update_date บอกว่ามีการแก้ไขข้อมูลเมื่อไหร่

ในการใช้การจริงๆ เราจะทำการใส่ข้อมูล create_date ในตอน create record และในตอน update เราก็ใส่ข้อมุล update_date ด้วย หรือไม่ก็เปลี่ยนประเภทข้อมูลให้เป็น timestamp แล้วก็ให้มันอัพเดทข้อมูลทุกครั้ง ที่มีการเปลี่ยนแปลงข้อมูล

แต่เดี๋ยวก่อน Yii2 มีนวัตกรรมใหม่ที่จะทำให้คุณพ่อบ้านสบายขึ้น (เดี่ยวๆ ก่อน..) มันดียังไง?

ตามเอกสารเค้าบอกว่ามันสามารถใส่ข้อมูล timestamp ให้เองอัตโนมัติ เพียงแค่เราตั้งชื่อฟิวด์ created_at,updated_at และกำหนด type ใน mysql เป็น Integer หลังจากนั้น เพิ่มการเรียกใช้งาน TimestampBehavior ใน Model ของคุณ โดยเพิ่ม function behaviors() เข้าไปใน Model ที่คุณต้องการใช้งาน

<?php
use yii\behaviors\TimestampBehavior;
public function behaviors()
{
    return [
        TimestampBehavior::className(),
    ];
}
?>

หลังจากกำหนดค่าแล้วหากมีการ create,update record TimestampBehavior จะใส่ข้อมูลให้เองอัตโนมัติ สะดวกมากๆ ครับ อย่าลืม!.. วิธีนี้ต้องกำหนดชื่อฟิวด์เป็น created_at,updated_at เท่านั้นครับ

แต่หากใครไม่ได้กำหนดชื่อฟิวด์ตามนี้ก็สามารถกำหนดให้ TimestampBehavior ให้มันได้รู้จักฟิวด์ create,update ได้ ดูตัวอย่างด้านล่าง

<?php
use yii\db\Expression;
use yii\behaviors\TimestampBehavior;
public function behaviors()
{
    return [
        [
            'class' => TimestampBehavior::className(),
            'createdAtAttribute' => 'create_time',
            'updatedAtAttribute' => 'update_time'
        ],
    ];
}
?>

เมื่อดูข้อมูใน db จะได้ข้อมูลเป็นเลข 1435245364 ประมาณนี้

แต่ถ้าคุณไม่อยากเก็บเป็น timestamp อยากเก็บเป็น format ธรรมดา แบบนี้ 2015-03-20 10:32:48 ก็สามารถทำได้โดยเพิ่ม 'value' => new Expression('NOW()') เข้าไป

<?php
use yii\db\Expression;
use yii\behaviors\TimestampBehavior;
public function behaviors()
{
    return [
        [
            'class' => TimestampBehavior::className(),
            'createdAtAttribute' => 'create_time',
            'updatedAtAttribute' => 'update_time',
            'value' => new Expression('NOW()'),
        ],
    ];
}
?>

จากนั้นเมื่อดูใน db ก็จะพบข้อมูล ประมาณนี้ 2015-03-20 10:32:48

เราสามารถสั่งให้มันเรียกข้อมูล timestame ให้ฟิวด์นั้นๆ โดยตรง ได้โดยใช้คำสั่ง touch เพื่อใช้ในกรณีที่ เราต้องการเซ็ตค่าที่ไม่ต้องรอเวลาตาม event

$model->touch('creation_time');

การใช้งานกับ GridView

 <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            'created_at:dateTime', // แสดงเฉพาวันที่ แสดงวันที่เวลา
            'updated_at:date', // แสดงเฉพาวันที่
            // กำหนดเอง อ่านเพิ่มเติม link ด้านล่าง
            ['attribute'=>'created_at','format'=>'html','value'=>function($model, $key, $index, $column){
                return Yii::$app->formatter->asDate($model->created_at,'medium'); //short,medium,long,full
                //return Yii::$app->formatter->asDateTime($model->created_at,'medium');
            }],

        ]
])
?>

การใช้งานกับ DetailView

   <?= DetailView::widget([
        'model' => $model,
        'attributes' => [
            'created_at:date', // แสดงเฉพาวันที่
            'updated_at:dateTime',// แสดงเฉพาวันที่ แสดงวันที่เวลา
             // กำหนดเอง อ่านเพิ่มเติม link ด้านล่าง
            [
                'attribute' => 'updated_at',
                'format'=>'html',
                'value' => Yii::$app->formatter->asDate($model->created_at,'medium')
            ]
        ],
    ]) ?>

อ่านการใช้งาน formatter เพิ่มเติมได้ที่นี่