ปัญหาของวันที่นั้นค่อนข้างสำคัญ ในประเทศไทย ส่วนใหญ่ใช้รูปแบบ พุทธศักราช เช่น 30/04/2559 แต่เมื่อบันทึกในฐานข้อมูลจะกลายเป็นคนละเรื่อง หากบันทึกลักษณะนี้ก็จะไม่สามารถนำมาคำนวณได้ต้องเขียนโปรแกรมวุ่นวายกันใหญ่ จะหาทางแก้อย่างไรให้พิมพ์ 30/04/2559 แล้วไปบันทึกในฐานข้อมูลเป็น 2016-04-30 ให้อัตโนมัติ หรือใส่เวลาด้วย เช่น พิมพ์ 30/04/2559 12:30:45 แล้วไปบันทึกเป็น 2016-04-30 12:30:45 แบบอัตโนมัติ
ทางออกคือการกำหนดในระดับ Model เป็นการเปลี่ยนข้อมูลโดยใช้ method พิเศษของ Model คือ beforeSave() และ afterFind() เข้ามาช่วย และเขียนโปรแกรมในการแปลงค่า
ในกรณีศึกษานี้หากใช้ Yii Framework 2 ร่วมกับฐานข้อมูล Microsoft SQL Server ซึ่งเป็นการเก็บข้อมูลแบบ datetime2 ให้เปลี่ยน dbType == 'datetime2' ถ้าใช้ MySQL ให้เปลี่ยนเป็น dbType == 'datetime'
สร้าง Model MyActiveRecord
สร้าง model ใหม่ใน common/models/MyActiveRecord.php
<?php
namespace common\models;
use yii\db\ActiveRecord;
class MyActiveRecord extends ActiveRecord
{
public function beforeSave($insert)
{
foreach($this->getTableSchema()->columns as $column) //loop column ทั้งหมด
{
$attribute = $this->getAttribute($column->name);
if(empty($attribute)){ //หากได้ค่าว่าง
$column->allowNull == 1 ? $this->setAttribute($column->name, null) : null;//ได้ตั้งค่า allow null ไหม ถ้าใช่ให้ใส่ null
}else if($column->dbType == 'datetime' && preg_match('/(\d{1,2}\s?\/\s?\d{1,2}\s?\/\s?\d{4}\s?\w*)/', $attribute)){ //ถ้ารูปแบบเป็น datetime
if(stripos($attribute,':') !== false){//ค้นหาตำแหน่ง : case-insensitive //ถ้ามีเวลาด้วย
$date_time = explode(' ', $attribute); //แยกวันที่กับเวลาด้วย space
$time = ' ' . trim($date_time[1]);
}else{//ถ้าไม่มีเวลา
$date_time[0] = $attribute;
$time = '';//เวลาว่าง
}
$dmy = preg_split('/(\s?\/\s?)/', $date_time[0]); //แยก วัน/เดือน/ปี
$year = (int) $dmy[2];//กำหนดเป็น int เพื่อการคำนวณ
$year = $year - 543;//ปี พ.ศ.-543
$result = $year . '-' . $dmy[1] . '-' . $dmy[0] . $time;//ได้รูปแบบ 2016-05-20
$this->setAttribute($column->name, $result);//กำหนดค่าใหม่
}
}
return parent::beforeSave($insert);
}
public function afterFind()
{
foreach($this->attributes as $column_name => $value){
if(preg_match('/(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/', $value)){ //ถ้ามีค่าในรูปแบบ 2016-05-20 13:30:45
if($value == '0000-00-00 00:00:00'){ //ถ้าไม่มีข้อมูล
$this->setAttribute($column_name, null); //กำหนดให้เป็นค่าว่าง
}else{
$date_and_time = explode('.', $value);
$date_time = explode(' ', $date_and_time[0]); //แยกวันและเวลา
if($date_time[1] == '00:00:00'){ //ถ้าเวลาว่าง
$date_time[1] = ''; //ไม่มีเวลา
}else{// ถ้ามีเวลา
$date_time[1] = ' ' . $date_time[1];//กำหนดเวลา
}
$ymd = explode('-', $date_time[0]);//แยก ปี-เดือน-วัน
$year = (int) $ymd[0];//กำหนดให้เป็น int เพื่อการคำนวณ
$year = $year + 543;// นำปี +543
$result = $ymd[2] . '/' . $ymd[1] . '/' . $year . $date_time[1];//ได้รูปแบบ วัน/เดือน/ปี ชั่วโมง:นาที:วินาทีี
$this->setAttribute($column_name, $result);//กำหนดค่าใหม่
}
}
}
return parent::afterFind();
}
}
ตัวอย่างการนำไปใช้งาน
ตั้งค่า Model ให้สืบทอด (extends) มาจาก common/models/MyActiveRecord
<?php
namespace common\models;
use Yii;
use common\models\MyActiveRecord;
class Datetimetest extends MyActiveRecord
{
public static function tableName()
{
return 'datetimetest';
}
public function rules()
{
return [
[['datetime1', 'datetime2'], 'required'],
[['datetime1', 'datetime2'], 'safe'],
];
}
public function attributeLabels()
{
return [
'id' => 'ID',
'datetime1' => 'Datetime1',
'datetime2' => 'Datetime2',
];
}
public function attributeHints()
{
return [
'datetime1' => 'ตัวอยาง 13/05/2559 01:20:30',
'datetime2' => 'ตัวอย่าง 13/05/2559 01:20:30',
];
}
}
ตัวอย่างการสร้างฟอร์มร่วมกับ MaskedInput
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\widgets\MaskedInput;
?>
<div class="datetimetest-form">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'datetime1')->widget(MaskedInput::className(), [
'mask' => '99/99/9999 99:99:99',
]) ?>
<?= $form->field($model, 'datetime2')->widget(MaskedInput::className(), [
'mask' => '99/99/9999 99:99:99',
]) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
ตัวอย่างการแสดงผล
เมื่อเพิ่มข้อมูล
เมื่อแก้ไขข้อมูล
เมื่อเปิดดู
ค่าที่บันทึกในฐานข้อมูล
ความคิดเห็น