fb_ads

www.รับเขียนโปรแกรม.net รับเขียนโปรแกรม ระบบต่างๆ เช่น ระบบข้อมูลบุคคล ระบบข้อมูลลูกค้า ระบบซื้อขาย คลังสินค้า ระบบเช่าจอง ทำงานบน Website ด้วย PHP MySql NodeJs HTML5 JavaScript Ajax

การตั้งค่าไฟล์ .htaccess บน web server ( ที่ไม่มีรองรับ NodeJS มีแต่ PHP ) เพื่อแก้ปัญหา Route ของ React Application

เมื่อเรา แต่ต้องการ upload ขึ้น host ซึ่งอาจเป็น shared host ธรรมดาเช่น hostgator หรือ godaddy เป็นต้นซึ่งปัญหาที่เจอ คือ เมื่อเราสร้าง route โดยใช้ browser router  หาก ผู้ใช้เข้ามาตาม path ที่เรากำหนดไว้ในครั้งแรกจะไม่สามารถเข้าได้ ผู้ใช้ต้องเข้าเข้าจากหน้าแรกก่อน

ในบทความนี้ จะแสดงวิธีแก้ปัญหา การใช้งาน BrowserRouter ของ react กับการ upload ขึ้น shared host ธรรมดา

รับเขียนโปรแกรม React



กรณีที่พัฒนา react โดยใช้ create-react-app  และ สมมุติว่าเรามี code ใน folder src ดังนี้ 

( ในตัวอย่างนี้ใช้ react-router-dom version 6  )

ไฟล์ master_page.js

import { useNavigate } from "react-router-dom";

const MasterPage=(props)=>{

    const navigate=useNavigate();

    return (<div>

        <div>
            <button onClick={event=>{ navigate("/page1") }} >Page1</button>
            <button onClick={event=>{ navigate("/page2") }} >Page2</button>
        </div>

        <hr />
        {props.children}

    </div>);

}

export default MasterPage;

ไฟล์ page1.js

import MasterPage from "./master_page";

const Page1=()=>{
    return <MasterPage>
        <h1>This is Page1 --- </h1>
    </MasterPage>
}

export default Page1;

ไฟล์ page2.js

import MasterPage from "./master_page";

const Page2=()=>{

    return <MasterPage>
        <h1>This is Page2 --- </h1>
    </MasterPage>
}

export default Page2;

ไฟล์ app.js

import Page1 from "./page1";
import Page2 from "./page2";

import {Routes, Route, BrowserRouter} from "react-router-dom";

function App() {
  return (
   <>
    <BrowserRouter>
        <Routes>

          <Route index  element={<Page1 />} />
          <Route path="page1"  element={<Page1 />} />
          <Route path="page2"  element={<Page2 />} />
         
        </Routes>
      </BrowserRouter>
   </>
  );
}

export default App;

จาก Code ดังกล่าว จะเห็นว่าเราสร้าง Route ของหน้าเว็บได้แก่ /page1 และ /page2 

และเมื่อเราทำการ build โดยใช้คำสั่ง npm run build แล้ว จะได้ folder ชื่อ build 

( โดยกรณีนี้ก่อน build ให้ กำหนด homepage ในไฟล์ package.json เพื่อให้ใช้ได้กับทุก domain )


เมื่อ รันคำสั่ง npm run build แล้ว ใน folder project จะมี folder build เพิ่มขึ้นมาซึ่งเราจะนำไฟล์ใน folder build นี้ upload ขึ้นไปไว้ที่ host


ปัญหาคือเมื่อเราใช้ BrowserRouter เราไม่สามารถเข้าผ่าน http://domain.com/page2 โดยตรงได้ จะต้องผ่าน http://domain.com/ คือหน้าแรกก่อนแล้วกด link ไป Page2 ถึงเข้า Page2 ได้เราสามารถกำหนดไฟล์ .htaccess และ Upload ไปที่ server ( Folder ที่เก็บไฟล์เว็บ ) เพื่อแก้ปัญหานี้ได้ ดังนี้

RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule . /index.html [L]

เพื่อระบุว่าหากเข้ามาใน path ที่ไม่มีอยู่ให้เรียกไฟล์ index.html

ตัวอย่างการสร้างกราฟวงกลม ( pie chart) บนหน้าเว็บ ด้วย PHP MySQL และ Javascript

เราสามารถแสดงหน้ารายงานโดยอ่านข้อมูลออกมาจากฐานข้อมูล mysql ออกมาแสดงเป็นกราฟวงกลมได้ดังนี้

Link ที่เกี่ยวข้อง สร้างกราฟแท่งด้วย javascript ( โดยใช้ chartjs และดึงข้อมูลมาจาก Firebase database )

Link ที่เกี่ยวข้อง สร้างกราฟแท่งด้วย ChartJs.org ตอน 2 ( สร้างกราฟแบบ DataSet เดียว )

รับเขียนโปรแกรม PHP MySQL Javascript

 1. สร้างไฟล์ get_data.php สำหรับอ่านข้อมูลจาก MySQL

<?php

    /*กำหนด username password และ database name ของ mysql */
    $servername = "localhost";
    $username = "...";
    $password = "...";
    $dbname = "...";

     /*------เชื่อมต่อ Database----*/
    $conn = new mysqli($servername, $username, $password, $dbname);
    
    if ($conn->connect_error) {
      die("Connection Error: " . $conn->connect_error);
    }

     /*------ถ้ายังไม่มีตาราง ให้สร้างตาราง ชื่อ food----*/
    $sql = "CREATE TABLE IF NOT EXISTS population  (
        country VARCHAR(100),
        population INT(8)
      )";

    $conn->query($sql);


    $sql = "SELECT * FROM population";
    $result = $conn->query($sql);

    if ($result->num_rows == 0)
    {
        /*----ถ้ายังไม่มีข้อมูลในตาราง population ให้เพิ่มข้อมูลเข้าไป----*/

        $sql = "INSERT INTO population (country, population)
        VALUES ('China', '1448178826')";
        $conn->query($sql);

        $sql = "INSERT INTO population (country, population)
        VALUES ('India', '1401891297')";
        $conn->query($sql);

        $sql = "INSERT INTO population (country, population)
        VALUES ('U.S.A.', '334107942')";
        $conn->query($sql);

        $sql = "INSERT INTO population (country, population)
        VALUES ('Indonesia', '278196711')";
        $conn->query($sql);

        $sql = "INSERT INTO population (country, population)
        VALUES ('Pakistan', '227952794')";
        $conn->query($sql);
    }
    //อ่านข้อมูล Popuplation จาก Database
    $sql = "SELECT * FROM population";
    $result = $conn->query($sql);
    //ส่งออกข้อมูลกลับไปที่ web browser ในรูปแบบ JSON
    $rows = array();
    while($r = mysqli_fetch_assoc($result)) {
        $rows[] = $r;
    }
    echo json_encode($rows);


?>

 

2.สร้างไฟล์ index.html สำหรับ แสดงกราฟวงกลม

<!DOCTYPE html>
<html lang="en-US">
<head>
    <meta charset="utf-8">
    <title>ตัวอย่างกราฟวงกลม</title>
    <!-- import javascript สร้าง  pie chart และ axios เพื่อดึงข้อมูลจาก MySQL แบบ ajax -->
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>

<!-- สร้าง div สำหรับแสดงกราฟ -->
<div id="piechart"></div>

<script type="text/javascript" >
    //ดึงข้อมูลแบบ ajax โดยเรียกไฟล์ get_data.php
    axios.get("get_data.php").then(response=>{

        google.charts.load('current', {'packages':['corechart']});
        google.charts.setOnLoadCallback(function(){
            //เก็บข้อมูล JSON ที่ส่งจากไฟล์ get_data.php ไว้ในตัวแปร data_from_mysql
            var data_from_mysql=response.data;
            var data=[];//สร้างตัวแปรสำหรับข้อมูลที่จะไปแสดงในกราฟ
            data.push(['Country', 'Popupulation']);
            //เพิม Country และ Population ที่ได้จาก MySQL เข้าไปใน data
            data_from_mysql.map(item=>{
                data.push([item.country,parseInt(item.population)]);
            });
            
            // กำหนดชื่อกราฟ ความกว่าง และความยาว
            var options = {
                'title':'World Population',
                'width':650,
                'height':400,
                sliceVisibilityThreshold:.00001
            };

            // สร้างกราฟในtag <div> ที่มี id เป็น "piechart"
            var chart = new google.visualization.PieChart(document.getElementById('piechart'));
            chart.draw(google.visualization.arrayToDataTable(data), options);
        });

    });
</script>

</body>
</html>

 

ผลลัพธ์ที่ได้คือ

 

ReactBootrap ตอน 3 สร้างตัวเลือกปฎิทินภาษาไทยแบบ ปี พ.ศ. ( DatePicker ) ด้วย React + Bootstrap


รับเขียนโปรแกรม ReactJS

เชื่อว่านักพัฒนาหลายคนต้องเคยมีปัญหากับตัวเลือกปฎิทินที่อยากได้ในรูปแบบปี พ.ศ. และเดือนที่เป็นภาษาไทย เราได้เคยเสนอวิธีแก้ปัญหาไปแล้วในบทความ

แก้ปัญหา Jquery Datepicker ให้เป็นรูปแบบ ปี พ.ศ.

สร้างตัวเลือกปฎิทินสำหรับปี พศ แบบ Mobile ( โดยไม่ต้องใช้ jquery date picker )

แต่ในบทความนี้จะแสดงวิธีสร้างตัวเลือกปฎิทิน ( Date Picker ) แบบปี พ.ศ. โดยใช้ React และ Bootstrap ซึ่งมีขั้นตอนดังนี้


 

 1.  เปิด  command prompt สร้างโปรเจคโดย ใช้คำสั่ง npx-create-react-app react_date_picker


2. เข้าไปที่ folder react_date_picker โดยใช้คำสั่ง cd react_date_picker กด enter

install ReactBootstrap โดยใช้สำสั่ง npm install react-bootstrap bootstrap@5.1.3 --save


3. install icon font awesome โดยใช้คำสั่ง
npm i --save @fontawesome/fontawesome-svg-core แล้วกด enter
npm install --save @fontawesome/free-solid-svg-icons แล้วกด enter
npm install --save @fontawesome/react-fontawesome แล้วกด enter


 

4. เปิดโปรเจคใน VS Code โดยพิมพ์ code . แล้วกด enter


5. สร้างไฟล์ date_picker.js สำหรับ Component DatePicker เพิ่ม Code สำหรับปฎิทิน ดังนี้

 
import React, {useState,useImperativeHandle,useEffect,useRef,forwardRef} from "react";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faChevronLeft,faChevronRight,faTimes } from "@fortawesome/free-solid-svg-icons";

const DatePicker=forwardRef((props,ref)=>{

        const [show_cal,set_show_cal]=useState(false);
        const [year_arr,set_year_arr]=useState([]);

        const [date_value,set_date_value]=useState("");

        const [sel_month,set_sel_month]=useState("");
        const [sel_year,set_sel_year]=useState("");

        const [cal_row,set_cal_row]=useState([]);

        const get_value=()=>{

                return date_value;
        }

        const set_value=(date)=>{

                set_show_cal(false);
                set_date_value(date);

                date=date.trim();
                let date_arr=date.split("/");
                let m = date_arr[1].toString();
                m=m.length==1?"0"+m:m;
                let y = (parseInt(date_arr[2])-543).toString();

                set_sel_month(m);
                set_sel_year(y);

        }

        useImperativeHandle(ref ,()=>{
        
                return {
                    "get_value":get_value,
                    "set_value":set_value
                }
                
        });

        const go_next_month=()=>{

                let m=parseInt(sel_month);
                let y=parseInt(sel_year);
                m++;
                if(m==13)
                {
                        m=1;
                        y++;
                }

                m=m.toString();
                m=m.length==1?"0"+m:m;

                set_sel_month(m);
                set_sel_year(y);
        }

        const go_pre_month=()=>{

                let m=parseInt(sel_month);
                let y=parseInt(sel_year);
                m--;
                if(m==0)
                {
                        m=12;
                        y--;
                }

                m=m.toString();
                m=m.length==1?"0"+m:m;

                set_sel_month(m);
                set_sel_year(y);
        }

        const select_date=(d)=>{
                if(d=="")
                {
                    return;
                }

                d=d.toString();
                let m=sel_month.toString();
                let y=parseInt(sel_year)+543;

                d=d.length==1?"0"+d:d;
                m=m.length==1?"0"+m:m;

                set_date_value(d+"/"+m+"/"+y);
                set_show_cal(false);
        }

      
        useEffect(()=>{

                let min_year=0;
                let max_year=0;
                let year_arr=[];
                if(
                    (props.min_year!=null) && (props.max_year!=null ) &&
                    ( parseInt(props.min_year) <= parseInt(props.max_year) )
                )
                {
                        min_year=parseInt(props.min_year);
                        max_year=parseInt(props.max_year);
                }
                else
                {
                        let y=(new Date()).getFullYear();
                        min_year=y-2;
                        max_year=y+2;
                }

                do
                {
                     year_arr.push(min_year);
                     min_year++;

                }while(min_year < max_year)

                set_year_arr(year_arr);

        },[]);

        useEffect(()=>{
        
            if(show_cal)
            {
                if( sel_month=="" )
                {
                        let m=(new Date()).getMonth()+1;
                        m=m.toString();
                        m=m.length==1?"0"+m:m

                        set_sel_month(m);
                }

                if( sel_year=="" )
                {
                        let y=(new Date()).getFullYear();
                        if(y > parseInt(year_arr[year_arr.length-1]))
                        {
                                y=year_arr[year_arr.length-1];
                        }
                        y=y.toString();
                        set_sel_year(y);
                }
            }
                

        },[show_cal]);

        useEffect(()=>{
                
                if(sel_month=="" || sel_year==""){ return; }
                
                let d=new Date ( parseInt(sel_year),parseInt(sel_month)-1,1 );
                
                let arr=[];
                let temp=[];

                for(var i=0;i<d.getDay();i++)
                {
                        temp.push("");
                }

                while(d.getMonth()==(parseInt(sel_month)-1))
                {
                        let d_str=d.getDate().toString();
                        d_str=d_str.length==1?"0"+d_str:d_str;

                        temp.push(d_str);
                        if(d.getDay()==6)
                        {
                                arr.push(temp);
                                temp=[];
                        }
                        d.setDate(d.getDate() + 1);
                }

                if(temp.length!=0)
                {
                        while(temp.length!=7)
                        {
                                temp.push("");
                        }
                        arr.push(temp);
                }
               
                set_cal_row(arr);

        },[sel_year,sel_month]);

        return (<>
           
            <input  className="form-control form-control-sm"  value={date_value}
                    onClick={event=>{if(show_cal){set_show_cal(false);}else{set_show_cal(true);}}}
                    onChange={event=>{event.target.value="";}}
                    
            />
            {(show_cal)?
                <div className="mt-2 bg-white" style={{width:"100%"}} >

                        <div className="row">
                                <div className="col-3  text-end">
                                        <button type="button" className="btn btn-primary btn-sm" onClick={event=>{go_pre_month()}}>
                                                <FontAwesomeIcon icon={faChevronLeft} />
                                        </button>
                                </div>
                                <div className="col-3">
                                    <select className="form-select form-select-sm" value={sel_month} onChange={event=>set_sel_month(event.target.value)}>
                                            <option value="01">มกราคม</option>
                                            <option value="02">กุมภาพันธ์</option>
                                            <option value="03">มีนาคม</option>
                                            <option value="04">เมษายน</option>
                                            <option value="05">พฤษภาคม</option>
                                            <option value="06">มิถุนายน</option>
                                            <option value="07">กรกฎาคม</option>
                                            <option value="08">สิงหาคม</option>
                                            <option value="09">กันยายน</option>
                                            <option value="10">ตุลาคม</option>
                                            <option value="11">พฤศจิกายน</option>
                                            <option value="12">ธันวาคม</option>
                                    </select>
                                </div>
                                <div className="col-3">
                                    <select className="form-select form-select-sm" value={sel_year} onChange={event=>set_sel_year(event.target.value)}>
                                        {year_arr.map(item=>
                                                <option value={item} >{parseInt(item)+543}</option>        
                                        )}
                                    </select>
                                </div>
                                <div className="col-3">
                                        <button type="button" className="btn btn-primary btn-sm" onClick={event=>{go_next_month()}}>
                                                <FontAwesomeIcon icon={faChevronRight} />
                                        </button>
                                </div>
                        </div>

                        <table className="table table-sm mt-2" style={{width:"100%"}}>
                                <thead>
                                        <tr className="table-active text-center">
                                                <th>อา</th>
                                                <th>จ</th>
                                                <th>อ</th>
                                                <th>พ</th>
                                                <th>พฤ</th>
                                                <th>ศ</th>
                                                <th>ส</th>
                                        </tr>

                                </thead>
                                <tbody className="text-center">
                                        {cal_row.map(item=>
                                                <tr>
                                                        {item.map(item2=>
                                                                <td className="text-cenetr" style={{cursor:"pointer"}}
                                                                        onClick={event=>{select_date(item2)}}
                                                                >{item2}</td>
                                                        )}
                                                </tr>
                                        )}
                                </tbody>
                        </table>
                        
                        <div className="text-end">
                                <button className="btn btn-sm btn-danger" type="button" onClick={event=>{
                                        set_date_value("");
                                        set_show_cal(false);
                                }}>
                                        <FontAwesomeIcon icon={faTimes} />  ล้างข้อมูลปฎิทิน
                                </button>
                        </div>

                </div>
            :null}
            

        </>)

});

export default DatePicker;


 6. สำหรับการเรียกใช้งาน Component DatePicker

import 'bootstrap/dist/css/bootstrap.min.css';
import {useRef} from "react";
//นำเข้า Component DatePicker
import DatePicker from './date_picker';

function App() {

  //สร้างตัวแปรอ้างอิงค์ Component DatePicker โดยใช้ชื่อว่า DatePicker
  const date_picker=useRef();

  return (
    <div>
        <div className="container mt-5" >
          <div className="mb-3">
              <label  className="form-label">วันที่</label>
              {/* ----สร้าง Component DatePicker--- */}
              <DatePicker ref={date_picker} label="วันที่"  />
          </div>
          <div className="mb-3">
              <button className="btn btn-primary" type="button" onClick={event=>{
                date_picker.current.set_value("01/01/2565");
                //.set_value("วัน/เดือน/ปี พ.ศ. ")
              }} >
                Set Date Picker
              </button>
              &nbsp;
              <button className="btn btn-primary" type="button" onClick={event=>{
                alert(date_picker.current.get_value());
                //.get_value() สำหรับรับค่าวันที่ที่เลือกซึ่งจะ return ค่าเป็น string รูปแบบ "วัน/เดือน/ปี พ.ศ. "
              }} >
                Get Date Picker
              </button>
          </div>
        </div>
    </div>
  );

}

export default App;


ผลลัพธ์ที่ได้คือ