บักทึก และสร้าง event ใน fullcalendar อัพเดทปี 2020 ตอนที่ 4

บทความใหม่ ปีนี้ โดย Ninenik Narkdee
ฐานข้อมูลกิจกรรม fullcandar สร้าง event จากฐานข้อมูล บันทึกกิจกรรมลง ฐานข้อมูล

คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ ฐานข้อมูลกิจกรรม fullcandar สร้าง event จากฐานข้อมูล บันทึกกิจกรรมลง ฐานข้อมูล



เมื่อเราได้รู้จักการเรียกใช้งาน การตั้งค่า และรูปแบบกิจกรรม
ของ fullcalendar จากเนื้อหาในตอนที่ผ่านมาแล้ว ทบทวนได้ที่
    รูปแบบกิจกรรม event ใน fullcalendar อัพเดทปี 2020 ตอนที่ 3 http://niik.in/976

 
เนื้อหาในตอนต่อไปนี้ เราจะมาประยุกต์สำหรับการใช้งานจริง โดยจะให้แนวทางการ
สร้างฟอร์มสำหรับบันทึกข้อมูลกิจกรรมลงฐานข้อมูล และนำข้อมูลกิจกรรมที่บันทึกนั้น
มาสร้างและแสดงในรูปแบบ json เพื่อนำมาใช้ใน fullcalendar ตามรูปแบบที่เราต้องการ
    ก่อนเราไปที่โครงสร้างคำสั่ง sql สำหรับสร้างตารางเก็บข้อมูล กิจกรรม จะให้แนวทาง
โดยยก รูปแบบ json ที่ครอบคลุมหรือมี property ที่สำคัญทั้งหมด ดังนี้
 
[
  {
    "id": "18",
    "groupId": "20200601",
    "start": "2020-06-01",
    "end": "2020-06-07",
    "startTime": "12:00:00",
    "endTime": "15:00:00",
    "allDay": false,
    "title": "กิจกรรมทดสอบ",
    "url": "",
    "textColor": "#FFFFFF",
    "backgroundColor": "#03a9f4",
    "borderColor": "transparent",
    "daysOfWeek": [
      "1",
      "3",
      "4"
    ],
    "startRecur": "2020-06-01",
    "endRecur": "2020-06-08"
  }
]
 
    จากรูปแบบโครงสร้าง json ข้างต้น ไม่ได้หมายความว่า ถ้าเราจะสร้างตารางให้รองรับการใช้งาน จะต้องกำหนด
ทุกฟิลด์ข้อมูลตามโครงสร้างด้านบนนี้  โดยสามารถสรุปค่าที่ควรเก็บในฐานข้อมูลได้ดังนี้
 
[
  {
    "id": "18",
    "start": "2020-06-01",
    "end": "2020-06-07",
    "startTime": "12:00:00",
    "endTime": "15:00:00",
    "allDay": false,
    "title": "กิจกรรมทดสอบ",
    "url": "",
    "textColor": "#FFFFFF",
    "backgroundColor": "#03a9f4",
    "borderColor": "transparent",
    "daysOfWeek": [
      "1",
      "3",
      "4"
    ],
  }
]
 
    ค่าเหล่านี้เป็นค่าที่เราควรมีฟิลด์สำหรับเก็บลงฐานข้อมูล เราสามารถเพิ่มฟิลด์ที่กำหนดเอง ได้ เช่น กรณีที่ต้องการ
ให้มีรายละเอียด หรือเก็บรายละเอียดกิจกรรมเพิ่มเติม นอกจากหัวข้อหรือ title ที่มีอยู่ เราอาจจะเพิ่มฟิลด์ที่ชื่อ detail
เข้าไปด้วย ซึ่งจำไว้ว่าค่านี้ ไม่ใช่ค่าพื้นฐานของ fullcalendar แต่เป็นค่าเพิ่มเติมที่เราต้องการบันทึก จะได้อธิบายใน
ลำดับต่อๆ ไป
    เราจะได้รูปแบบคำสั่ง sql สำหรับสร้างตาราง event เป้นดังนี้
 
--
-- Table structure for table `tbl_event`
--

CREATE TABLE `tbl_event` (
  `event_id` int(11) NOT NULL,
  `event_title` varchar(256) NOT NULL,
  `event_detail` text NOT NULL,
  `event_startdate` date NOT NULL,
  `event_enddate` date NOT NULL,
  `event_starttime` time NOT NULL,
  `event_endtime` time NOT NULL,
  `event_color` varchar(15) NOT NULL DEFAULT '#FFFFFF',
  `event_bgcolor` varchar(15) NOT NULL DEFAULT '#03a9f4',
  `event_url` varchar(300) NOT NULL,
  `event_repeatday` varchar(20) NOT NULL,
  `event_allday` tinyint(1) NOT NULL,
  `event_createdate` timestamp NOT NULL DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Indexes for dumped tables
--

--
-- Indexes for table `tbl_event`
--
ALTER TABLE `tbl_event`
  ADD PRIMARY KEY (`event_id`);

--
-- AUTO_INCREMENT for dumped tables
--

--
-- AUTO_INCREMENT for table `tbl_event`
--
ALTER TABLE `tbl_event`
  MODIFY `event_id` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;
 
    โดยในฟิลด์ event_allday เราจะเก็บค่าเป็น 0 หรือ 1 สำหรับ ไม่เป็น หรือเป็น กิจกรรมทั้งวันตามลำดับ
     และในฟิลด์ event_repeatday เราจะเก็บค่าเป็นรูปแบบ string set ของวัน ที่จะทำซ้ำในรุปตัวเลข เช่น
วันจันทร์ พุธ ศุกร์ ก็จะเก็บเปฺ็น 1,3,4  เป็นต้น โดย 0 คือค่าเริ่มต้นของวันอาทิตย์
 
 

การสร้างฟอร์มบันทึกข้อมูลกิจกรรม

    เมื่อเราได้โครงสร้างตารางฐานข้อมูลสำหรับบันทึกกิจกรรมแล้ว เราจะทำการสร้างรูปแบบฟอร์มสำหรับบันทึกข้อมูล
โดยในที่นี้จะให้เป็นแนวทางเท่านั้น โดยกำหนดเฉพาะฟิลด์ที่สำคัญ  เวลานำไปใช้ หรือประยุกต์ ก็ปรับเพิ่มฟิลด์ค่า
ต่างๆ ตามต้องการ
    ดูตัวอย่างฟอร์มเพิ่มข้อมูลได้ที่ demo เรามีการใช้งาาน plugin datepcker และ timepicker ของ bootstrap 4
สำหรับใช้เลือกวันที่และเวลาประกอบนตัวอย่าง
 

    ไฟล์ form_calendar.php

<?php
// โค้ดไฟล์ dbconnect.php ดูได้ที่ http://niik.in/que_2398_5642
 require_once("dbconnect.php");
?>
<?php
// การบันทึกข้อมูลอย่างง่ายเบื้องตั้น
if(isset($_POST['btn_add']) && $_POST['btn_add']!=""){
	$p_event_title = (isset($_POST['event_title']))?$_POST['event_title']:"";
	$p_event_startdate = (isset($_POST['event_startdate']))?$_POST['event_startdate']:"0000-00-00";
	$p_event_enddate = (isset($_POST['event_enddate']))?$_POST['event_enddate']:"0000-00-00";
	$p_event_starttime = (isset($_POST['event_starttime']))?$_POST['event_starttime']:"00:00:00";
	$p_event_endtime = (isset($_POST['event_endtime']))?$_POST['event_endtime']:"00:00:00";
	$p_event_repeatday = (isset($_POST['event_repeatday']))?$_POST['event_repeatday']:"";
	$p_event_allday = (isset($_POST['event_allday']))?1:0;
	$sql = "
	INSERT INTO tbl_event SET
	event_title='".$p_event_title."',
	event_startdate='".$p_event_startdate."',
	event_enddate='".$p_event_enddate."',
	event_starttime='".$p_event_starttime."',
	event_endtime='".$p_event_endtime."',
	event_repeatday='".$p_event_repeatday."',
	event_allday='".$p_event_allday."'
	";
	$mysqli->query($sql);
	header("Location:form_calendar.php");
	exit;
}
?>
<!DOCTYPE html>
<html lang='en'>
  <head>
    <meta charset='utf-8' />
	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css">
	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tempusdominus-bootstrap-4/5.1.2/css/tempusdominus-bootstrap-4.min.css">
	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css">  
	<style type="text/css">
		.wrap-form{width:800px;margin: auto;}
	  </style>	
  </head>
  <body>

	<br>
	<br>
	  <div class="wrap-form">
<form action="" method="post" accept-charset="utf-8"> 
<div class="form-group row">
    <label for="event_title" class="col-sm-2 col-form-label text-right">หัวข้อกิจกรรม</label>
    <div class="col-12 col-sm-8">
      <input type="text" class="form-control" name="event_title"
       autocomplete="off" value="" required>      
      <div class="invalid-feedback">
        กรุณากรอก หัวข้อกิจกรรม
      </div>            
    </div>
</div>
<div class="form-group row">
    <label for="event_startdate" class="col-sm-2 col-form-label text-right">วันที่เริ่มต้น</label>
    <div class="col-12 col-sm-8">
        <div class="input-group date" id="event_startdate" data-target-input="nearest">
          <input type="text" class="form-control datetimepicker-input" name="event_startdate" data-target="#event_startdate"
           autocomplete="off" value="" required>           
            <div class="input-group-append" data-target="#event_startdate" data-toggle="datetimepicker">
                <div class="input-group-text"><i class="far fa-calendar-alt"></i></div>
            </div>
        </div>       
      <div class="invalid-feedback">
        กรุณากรอก วันที่เริ่มต้น
      </div>            
    </div>
</div>
<div class="form-group row">
    <label for="event_enddate" class="col-sm-2 col-form-label text-right">วันที่สิ้นสุด</label>
    <div class="col-12 col-sm-8">
        <div class="input-group date" id="event_enddate" data-target-input="nearest">
            <div class="input-group-prepend">
            	<div class="input-group-text"><i class="far fa-times-circle"></i></div>
            </div>           
          <input type="text" class="form-control datetimepicker-input" name="event_enddate" data-target="#event_enddate"
           autocomplete="off" value="" >           
            <div class="input-group-append" data-target="#event_enddate" data-toggle="datetimepicker">
                <div class="input-group-text"><i class="far fa-calendar-alt"></i></div>
            </div>
        </div>            
      <div class="invalid-feedback">
        กรุณากรอก วันที่สิ้นสุด
      </div>            
    </div>
</div>
<div class="form-group row">
    <label for="event_starttime" class="col-sm-2 col-form-label text-right">เวลาเริ่มต้น</label>
    <div class="col-12 col-sm-8">
        <div class="input-group date" id="event_starttime" data-target-input="nearest">
            <div class="input-group-prepend">
            	<div class="input-group-text"><i class="far fa-times-circle"></i></div>
            </div>           
          <input type="text" class="form-control datetimepicker-input" name="event_starttime" data-target="#event_starttime"
           autocomplete="off" value="" >           
            <div class="input-group-append" data-target="#event_starttime" data-toggle="datetimepicker">
                <div class="input-group-text"><i class="far fa-clock"></i></div>
            </div>
        </div>          
      <div class="invalid-feedback">
        กรุณากรอก เวลาเริ่มต้น
      </div>            
    </div>
</div>
<div class="form-group row">
    <label for="event_endtime" class="col-sm-2 col-form-label text-right">เวลาสิ้นสุด</label>
    <div class="col-12 col-sm-8">
        <div class="input-group date" id="event_endtime" data-target-input="nearest">
            <div class="input-group-prepend">
            	<div class="input-group-text"><i class="far fa-times-circle"></i></div>
            </div>           
          <input type="text" class="form-control datetimepicker-input" name="event_endtime" data-target="#event_endtime"
           autocomplete="off" value="" >           
            <div class="input-group-append" data-target="#event_endtime" data-toggle="datetimepicker">
                <div class="input-group-text"><i class="far fa-clock"></i></div>
            </div>
        </div>           
      <div class="invalid-feedback">
        กรุณากรอก เวลาสิ้นสุด
      </div>            
    </div>
</div>
<div class="form-group row">
    <label for="event_endtime" class="col-2 col-form-label text-right">ทำซ้ำวัน</label>
    <div class="col-12 col-sm-10 pt-2">
    	<?php
		$dayTH = array('อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.');
		?>
        <div class="input-group">
        <?php foreach($dayTH as $k => $day_value){?>
        <div class="form-check ml-3" style="width:50px;">
            <input class="custom-control-input repeatday_chk" type="checkbox" 
                name="event_repeatday_chk" id="event_repeatday_chk<?=$k?>"
                value="<?=$k?>">
            	<label class="custom-control-label" for="event_repeatday_chk<?=$k?>"><?=$day_value?></label>
        </div>    
		<?php } ?>
        <input type="hidden" name="event_repeatday" id="event_repeatday" value="" />
        </div>
        <br>    
    </div>
</div>
<div class="form-group row">
    <div class="col-10 offset-2 pl-5">
	<input class="custom-control-input" type="checkbox" 
        name="event_allday" id="event_allday"
        value="1">
    <label class="custom-control-label" for="event_allday">
        คลิกเลือกถ้าเป็นกิจกรรมทั้งวัน</label>
        <br>    
    </div>
</div>
<div class="form-group row">
    <div class="col-sm-2 offset-sm-2 text-right pt-3">
         <button type="submit" name="btn_add" value="1" class="btn btn-primary btn-block">เพิ่มข้อมูล</button>
    </div>
</div> 
</form>
		  </div>

<script  src="https://code.jquery.com/jquery-3.5.1.slim.min.js" 
	  integrity="sha256-4+XzXVhsDmqanXGHaHvgh1gMQKX40OUvDEBTu8JcmNs=" 
	  crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.26.0/moment-with-locales.min.js"></script>	  
<script src="https://cdnjs.cloudflare.com/ajax/libs/tempusdominus-bootstrap-4/5.1.2/js/tempusdominus-bootstrap-4.min.js"></script>	  

<script type="text/javascript">
	$(function () {
		// เมื่อเฃือกวันทำซ้ำ วนลูป สร้างชุดข้อมูล
		$(document.body).on("change",".repeatday_chk",function(){
			$("#event_repeatday").val("");
			var repeatday_chk = [];
			$(".repeatday_chk:checked").each(function(k, ele){
				repeatday_chk.push($(ele).val());
			});
			$("#event_repeatday").val(repeatday_chk.join(",")); // จะได้ค่าเปน เช่น 1,3,4
		});
		$('#event_startdate,#event_enddate').datetimepicker({
			format: 'YYYY-MM-DD'
		});
		$('#event_starttime,#event_endtime').datetimepicker({
			format: 'HH:mm'
		});		
		$(".input-group-prepend").find("div").css("cursor","pointer").click(function(){
			$(this).parents(".input-group").find(":text").val("");
		});			
	});
</script>
	  
	  
  </body>
</html>
 
    หลังจากทำการสร้างฟอร์มสำหรับเพิ่มข้อมูลเรียบร้อยแล้ว ให้เราทำการเพิ่มข้อมูล ตามรูปแบบต่างๆ ตามต้องการ
เพื่อเราจะทดสอบสำหรับแสดงข้อมูลเป็น json และนำมาใช้ในปฏิทิน fullcalendar
 
 

สร้าง event กิจกรรมในรูปแบบ json จากฐานข้อมูล

    จากตัวอย่างในตอนที่แล้ว เราใช้รูปแบบไฟล์ events.php โดยใช้โค้ดตัวอย่างจำลองข้อมูล แต่ในที่นี้ เราจะทำการ
ประยุกต์ โดยดึงข้อมูลจากฐานข้อมูล ที่เราได้เพิ่มกิจกรรมไว้เรียบร้อยแล้ว 
    แต่ก่อนอื่นเรามาดูการทำงานของ fullcalendar เมื่อมีการเปลี่ยนแปลงข้อมูลช่วงเวลาของเดือน ในปฏิทิน เช่น การ
เปลี่ยนเดือนไปเดือนก่อนหน้าหรือเดือนถัดไป ทุกครั้งที่เราทำการเปลี่ยนช่วงวันที่ในปฏิทิน ตัว ajax ก็จะทำการส่งค่า
วันที่และเวลาเริ่มต้น กับวินที่และเวลาสิ้นสุด มายังไฟล์ events.php เพื่อใช้สำหรับกรองหรือคิวรี่ข้อมูลตามช่วงเวลานั้นๆ
โดยทั่วไปจะมีค่าเป็น วันที่ 1 ของเดือนที่เรากำลังจะแสดง กับวันที่่ 1 ของเดือนถัดจากนั้น เช่น ปัจจุบันเราอยู่เดือน 6
ถ้าเราย้อนดูเดือนก่อนหน้า ก็จะเป็นเดือน 5 ค่าของ ตัวแปร start และ end ที่ส่งแบบ get ไปยังไฟล์ events.php ก็จะเป็น
2020-05-01T00:00:00 และ 2020-06-01T00:00:00 ซึ่งก็จะเป็นข้อมูลของเดือน 5 ทั้งหมดนั้นเอง ในลักษณะเดียวกัน
ถ้าตอนนี้เราอยู่เดือน 6 เหมือนเดิม แต่ต้องการเลื่อนไปดูเดือน 7 ข้อมูล ตัวแปร start และ end ที่ส่งแบบ get ไปยังไฟล์ 
events.php ก็จะเป็น 2020-07-01T00:00:00 และ 2020-06-08T00:00:00 ซึ่งก็จะเป็นข้อมูลของเดือน 7 ทั้งหมด
แต่อย่าลืมว่า ค่าจะเป็นตามนี้ได้ เราต้องกำหนด การตั้งค่า showNonCurrentDates: false, // แสดงวันที่ของเดือนอื่นหรือไม่
ตามตัวอย่างในตอนที่ 2 ทบทวน http://niik.in/975
    หากเรากำหนดค่า showNonCurrentDates เป็น true ปฏิทินจะแสดงวันที่ของเดือนอื่นๆ ในหน้าเดือนปัจจุบันด้วย และเวลา
เรียกใช้ ajax วันที่เริ่มต้น ก็จะเป้นวันที่แรกในปฏิทิน และวันที่สุดท้ายในปฏิทิน แทนนั่นเอง ตรงนี้เป็นข้อควรจำไว้
 
    ถึงเวลาเราสร้างไฟล์ json ดึงข้อมูลจากฐานข้อมูล และรับค่า start และ end มาช่วนในการกรองข้อมูลด้วย
จะได้ไฟล์ events.php เป็นดังนี้
 

ไฟล์ events.php

<?php
header("Content-type:application/json; charset=UTF-8");    
header("Cache-Control: no-store, no-cache, must-revalidate");         
header("Cache-Control: post-check=0, pre-check=0", false); 
// โค้ดไฟล์ dbconnect.php ดูได้ที่ http://niik.in/que_2398_5642
 require_once("dbconnect.php");
$json_data = array();

$sql ="
SELECT * FROM tbl_event WHERE event_startdate>='".$_GET['start']."' 
AND event_enddate<='".$_GET['end']."'
";
$result = $mysqli->query($sql);
if(isset($result) && $result->num_rows>0){
	while($row = $result->fetch_assoc()){
		$_start_date = $row['event_startdate'];
		$_end_date = false;
		$_start_time = false;
		$_end_time = false;
		$_repeat_day = false;
		$_all_day = ($row['event_allday']!=0)?true:false;
		if($row['event_starttime']!="00:00:00"){
			$_start_date = $row['event_startdate']."T".$row['event_starttime'];
			if($row['event_endtime']!="00:00:00" && ($row['event_starttime']==$row['event_enddate'] || 
			$row['event_enddate']=="0000-00-00") ){
				$_end_date = $row['event_startdate']."T".$row['event_endtime'];
			}
		}
		if($row['event_enddate']!="0000-00-00"){
			$_end_date = $row['event_enddate'];
			if($row['event_endtime']!="00:00:00"){
				$_end_date = $row['event_enddate']."T".$row['event_endtime'];
			}else{
				$_end_date = date("Y-m-d",strtotime($row['event_enddate']." +1 day"));
			}
		}
		if($row['event_enddate']!="0000-00-00" && $row['event_enddate']!=$row['event_startdate'] 
		&& $row['event_starttime']!="00:00:00" && $row['event_endtime']!="00:00:00" ){
			$_start_date = $row['event_startdate'];
			$_end_date = $row['event_enddate'];				
			$_start_time = $row['event_starttime'];
			$_end_time = $row['event_endtime'];		
			$_all_day = false;			
		}
		$arr_eventData = array(
			"id" => $row['event_id'],
			"groupId" => str_replace("-","",$row['event_startdate']),
			"allDay" => $_all_day,
			"start" => $_start_date,
			"end" => $_end_date,
			"startTime" => $_start_time,
			"endTime" => $_end_time,
			"title" => $row['event_title'],
			"url" => $row['event_url'],
			"textColor" => $row['event_color'],
			"backgroundColor" => $row['event_bgcolor'],
			"borderColor" => "transparent",
		);
		if($row['event_repeatday']!=""){
			$arr_eventData['daysOfWeek'] = explode(",",$row['event_repeatday']);
		}				
		if($row['event_enddate']!="0000-00-00" && $row['event_enddate']!=$row['event_startdate'] 
		&& $row['event_starttime']!="00:00:00" && $row['event_endtime']!="00:00:00" ){
			$arr_eventData['startRecur'] = $_start_date;
			$_end_date = date("Y-m-d",strtotime($row['event_enddate']." +1 day"));
			$arr_eventData['endRecur'] = $_end_date;
		}
		if(!$_all_day){unset($arr_eventData['allDay']);}
		if(!$_end_date){unset($arr_eventData['end']);}
		if(!$_start_time){unset($arr_eventData['startTime']);}
		if(!$_end_time){unset($arr_eventData['endTime']);}
		$json_data[] = $arr_eventData;
	}
}
// แปลง array เป็นรูปแบบ json string  
if(isset($json_data)){  
    $json= json_encode($json_data);    
    if(isset($_GET['callback']) && $_GET['callback']!=""){    
    echo $_GET['callback']."(".$json.");";        
    }else{    
    echo $json;    
    }    
}
?>
 
    เท่านี้เราก็จะได้รูปแบบข้อมูล json ที่สามารถแสดงข้อมูลรองรับรูปแบบกิจกรรมต่างๆ แทนข้อมูลจำลอง เป็นข้อมูล
ที่ได้จากฐานข้อมูลที่เราจัดเก็บไว้




กด Like หรือ Share เป็นกำลังใจ ให้มีบทความใหม่ๆ เรื่อยๆ น่ะครับ



อ่านต่อที่บทความ









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









URL สำหรับอ้างอิง











เว็บไซต์ของเราให้บริการเนื้อหาบทความสำหรับนักพัฒนา โดยพึ่งพารายได้เล็กน้อยจากการแสดงโฆษณา โปรดสนับสนุนเว็บไซต์ของเราด้วยการปิดการใช้งานตัวปิดกั้นโฆษณา (Disable Ads Blocker) ขอบคุณครับ