แนะนำการใช้งาน ADOdb PHP Database Abstraction Layer

บทความใหม่ เดือนที่แล้ว โดย Ninenik Narkdee
database php adodb database abstraction layer

คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ database php adodb database abstraction layer





เนื้อหานี้จะมาแนะนำ และศึกษาการใช้งาน ADOdb ซึ่งเป็น
Database Abstraction Layer รูปแบบหนึ่ง ที่เราสามารถใช้
จัดการเกี่ยวกับฐานข้อมูลใน PHP ได้สะดวก และที่สำคัญหลัก
ก็คือรองรับการปรับใช้กับ platform ฐานข้อมูลอื่น นอกจาก 
MySQL ได้โดยไม่ต้องแก้ไขโค้ด หรือรูปแบบคำสั่งใหม่ทั้งหมด
เพียงแค่ปรับ driver หรือประเภท platform ที่จะใช้งาน และปรับ
แต่งค่าเล็กน้อย ก็สามารถใช้งานได้ เหมาะสำหรับใครที่อาจวาง
แผนหรือมีแนวโน้มที่จะนำโค้ดที่สร้างขึ้นมา ไปใช้งานกับ database
server ที่หลากหลายในอนาคต
    Database Abstraction Layer เข้าใจอย่างง่าย ก็คือรูปแบบการจัดการ
ที่เป็นเครื่องมือที่ช่วยสำหรับการเชื่อมต่อและจัดการระหว่างตัว aplication
หรือโปรแกรม ในที่นี้คือเว็บโปรแกรม เข้ากับฐานข้อมูลต่างๆ  อย่างที่เราเข้าใจ
ว่าแต่ละ platform ฐานข้อมูล ก็จะมีรูปแบบการจัดการ และการใช้งานเหมือน หรือ
แตกต่างกันไปตามแต่ละกรณี หากเราต้องการให้ app ของเรา รองรับการใช้งานร่วมกับ
platform ฐานข้อมูลที่หลากหลาย โดยไม่ต้องเขียนโค้ดใหม่ทุกครั้ง การใช้ตัวช่่วย
สำหรับจัดการกับฐานข้อมูล ถือว่าเป็นวิธีการที่เหมาะสมที่น่าจะนำมาใช้ 
 
 
 

การติดตั้ง ADOdb

    ในการใช้งาน ADOdb จะใช้กับ PHP >= 7.2 เป็นต้นไป
    สามารถเลือกติดตั้งได้ทั้งผ่าน Composer โดยใช้รูปแบบคำสั่งดังนี้
 
composer require adodb/adodb-php ^5.20
 
    แล้วเรียกใช้งานผ่าน autoload ไฟล์
 
<?php
// include composer autoload
require_once './vendor/autoload.php';
 
    หรือจะเข้าไปดาวน์โหลดจาก http://sourceforge.net/projects/adodb/files/latest/download
    จากนั้นแตกไฟล์ ใช้งานเฉพาะโฟลเดอร์ของ ADOdb แล้ว include มาใช้งานประมาณนี้
 
<?php
// include adodb
include './adodb5/adodb.inc.php';
 
 
 

การเชื่อมต่อฐานข้อมูลผ่าน ADOdb

    ในที่นี้เราจะจำลองหรือใช้งานไปกับ mysqli ขั้นตอนแรกของการกำหนดการเชื่อมค่อกับฐานข้อมูล
คือการกำหนด driver ที่จะใช้งาน ในรูปแบบดังนี้
 
<?php
include './adodb5/adodb.inc.php';

$driver = 'mysqli'; // เลือก driver
$db = newAdoConnection($driver);

// กำหนดค่าสำหรับการเชื่อมต่อฐานข้อมูล
$db->connect('localhost', 'root', '', 'test');
 
    ค่า parameter สำหรับการเชื่อมต่อฐานข้อมูล หลักๆ จะประกอบไปด้วย host username password
และ database name
    เราสามารถตรวจสอบเงื่อนไขว่าทำการเชื่อมต่อฐานข้อมูลได้หรือไม่โดยใช้คำสั่ง
 
$db->connect('localhost', 'root', '', 'test');
if($db->isConnected()){
    echo "Connected";
}
 
    หรือต้องการแจ้งถ้าเชื่อมต่อไม่สำเร็จ
 
$db->connect('localhost', 'root', '', 'test');
if(!$db->isConnected()){
    die("Can't connect to Database Server");
}
 
    การกำหนด charset สามารถทำได้ดังนี้
 
$db->connect('localhost', 'root', '', 'test');
if(!$db->isConnected()){
    die("Can't connect to Database Server");
}
$db->setCharset('utf8');
 
     การปิดการเชื่อมต่อฐานข้อมูลจะใช้คำสั่ง
 
$db->close();
 
    อย่างไรก็ตาม เราไม่จำเป็นต้องกำหนดคำสั่งนี้ก็ได้ เนื่องจากทันทีที่คำสั่ง PHP ทำงานเสร็จแล้ว ก็จะ
ปิดการเชื่อมต่อฐานข้อมูลโดยอัตโนมัติ
 
 
 

การคิวรี่คำสั่ง SQL

    เราสามารถเลือกใช้งานคำสั่ง สำหรับคิวรี่คำสั่ง SQL ตามรูปแบบการใช้งาน 
 

    getAll()

    สำหรับคิวรี่คำสั่ง SQL และแสดงข้อมูลทั้งหมด คืนค่าเป็นข้อมูล array ผลลัพธ์ ไม่ควรใช้งานกับข้อมูล
ที่มีจำนวนมากเกินไป
 
$sql = "select province_id,province_name from tbl_provinces";
$result = $db->getAll($sql);
if($result){
    foreach ($result as $row){
        echo $row['province_name']."<br>";
    }
}
 
    ปกติแล้ว ตัวแปร array ผลลัพธ์ที่ได้ จะมีรูปแบบเหมือนเรียกใช้งานคำสั่ง mysqli_fetch_array ดูตัวอย่าง
array ผลลัพธ์
 
Array
(
    [0] => Array
        (
            [0] => 1
            [province_id] => 1
            [1] => กรุงเทพมหานคร
            [province_name] => กรุงเทพมหานคร
        )

)
 
    สังเกตว่า key ของผลลัพธ์เป็นทั้ง ตัวเลข และข้อความ เราสามารถที่จะเลือกเฉพาะอย่างใด อย่างหนึ่งได้
เช่นเป็นตัวเลขอย่างเดียว(* ส่วนใหญ่ไม่นิยม) หรือแบบเป็นตัวอักษรอย่างเดียว หรือทั้งสองแบบ ตามตัวอย่าง
ด้านบน ซึ่งจริงๆ แล้วหากเราไม่ใช้งานแบบใดแบบหนึ่งเลย เช่นไม่ใช้แบบตัวเลขเลย เราควรเลือกอย่างใด
อย่างหนึ่งจะช่วยในเรื่องของการลดการใช้งานที่ไม่จำเป็นออกได้
    เราสามารถจัดการผลลัพธ์ของข้อมูลโดยสามารถกำหนดผ่าน ตัวแปร $ADODB_FETCH_MODE 
หรือกำหนดผ่านฟังก์ชั่น setFetchMode() ประมาณนี้ได้
 
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
// $db->setFetchMode(ADODB_FETCH_ASSOC);
$sql = "select province_id,province_name from tbl_provinces LIMIT 1";
$result = $db->getAll($sql);
 
    ผลลัพธ์ทีได้
 
// ADODB_FETCH_ASSOC
Array
(
    [0] => Array
        (
            [province_id] => 1
            [province_name] => กรุงเทพมหานคร
        )

)
// ADODB_FETCH_NUM
Array
(
    [0] => Array
        (
            [0] => 1
            [1] => กรุงเทพมหานคร
        )

)
// ADODB_FETCH_BOTH 
Array
(
    [0] => Array
        (
            [0] => 1
            [province_id] => 1
            [1] => กรุงเทพมหานคร
            [province_name] => กรุงเทพมหานคร
        )

)
 
    เราสามารถกำหนด $ADODB_FETCH_MODE การทำคำสั่ง คิวรี่แต่ละครั้ง เพื่อให้ได้รูปแบบผลลัพธ์
ที่แตกต่างกันไปได้
 
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;  
 $rs1 = $db->getAll('select * from table');  
 
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;  
 $rs2 = $db->getAll('select * from table'); 
 
    ในกรณีที่ใช้เป็นแบบ ตัวอักษร เรายังสามารถระบุให้เป็นตัวพิมพ์ใหญ่ หรือตัวพิมพ์เล็ก อย่างเดียวก็ได้
โดยกำหนดผ่านตัวแปรค่าคงที่ชื่อ ADODB_ASSOC_CASE ตัวอย่างเช่น
 
include './adodb5/adodb.inc.php';
define('ADODB_ASSOC_CASE', ADODB_ASSOC_CASE_UPPER);
// รองรับค่า ADODB_ASSOC_CASE_LOWER ADODB_ASSOC_CASE_UPPER
// และ ADODB_ASSOC_CASE_NATIVE
 
    อย่าลืมว่าการเปลี่ยนชื่อของฟิลด์ มีผลตอนเรียกใช้งาน ถ้าเรากำหนดเป็นตัวพิมพ์ใหญ่ทั้งหมด
เวลาเรียกใช้งาน เราก็ต้องกำหนดเป็นตัวพิมพ์ใหญ่ด้วย เช่น $row['PROVINCE_NAME"] เป็นต้น
 
 

    getAssoc()

    คำสั่งนี้จะคืนค่าเป็น array ข้อมูลผลลัพธ์ โดยจะใช้ primary key เป็น key หลักของ array ข้อมูล
ไม่เหมือนคำสั่ง getAll() ที่เริ่มต้น key หลักผลลัพธ์ที่ 0  ดูตัวอย่าง
 
$sql = "SELECT * FROM tbl_provinces";
$result = $db->getAssoc($sql);
if($result){
    foreach ($result as $row){
        echo $row['province_name']."<br>";
    }
}
 
    ผลลัพธ์ทีได้
 
กรุงเทพมหานคร
Array
(
    [1] => Array
        (
            [province_code] => 10
            [province_name] => กรุงเทพมหานคร
            [province_name_eng] => Bangkok
            [geo_id] => 2
            [last_update] => 2018-09-19 12:11:03
        )

)
 
    สังเกตว่าตัว primary key หรือ province_id จะไม่อยู่ใน array ข้อมูล แต่จะมีแค่ค่าของข้อมูล หรือ
province_id เท่ากับ 1 เป็น key ของ array แทน
    ถ้าเราเรียกแสดงเฉพาะฟิลด์ที่ต้องการ ดูตัวอย่าง
 
$sql = "SELECT province_id,province_name FROM tbl_provinces";
$result = $db->getAssoc($sql);
 
     ผลลัพธ์ทีได้
 
Array
(
    [1] => กรุงเทพมหานคร
    [2] => สมุทรปราการ
)
 
    จะเห็นตัวตัว ฟิลด์แรก จะกลายเป็น key และฟิดล์ที่สองจะเป็นเป็น value 
    เราลองกำหนดมากกว่าสองฟิลด์ จะได้เป็น
 
$sql = "SELECT province_code,province_id,province_name FROM tbl_provinces ";
$result = $db->getAssoc($sql);
 
     ผลลัพธ์ทีได้
 
Array
(
    [10] => Array
        (
            [province_id] => 1
            [province_name] => กรุงเทพมหานคร
        )

    [11] => Array
        (
            [province_id] => 2
            [province_name] => สมุทรปราการ
        )

)
 
    ตัวที่กำหนดเป็นฟิลด์แรก จะกลายเป็น key ของข้อมูลหลัก สังเกต่วา province_code จะเป็น key ของ
array ข้อมูล และไม่รวมอยู่ในข้อมูลที่เหลือ
    รูปแบบคำสั่งนี้ เหมาะสำหรับสร้างชุดตัวแปรข้อมูลที่มีความสัมพันธ์กัน เพื่อให้สามารถนำไปใช้งานต่อได้
โดยลดขั้นตอนในการกำหนดตัวแปร หรือสร้างรูปแบบ array ข้อมูลใหม่
 
 

    selectLimit()

    อย่างที่เราทราบว่า การเขียนคำสั่ง SQL ให้รองรับการทำงานในหลายๆ platform เราควรใช้รูปแบบคำสั่ง
ที่ถูกต้องและเหมาะสม เพราะในแต่ละคำสั่ง จะถูกแปลงและนำไปปรับใช้งานตามแต่ละ driver ที่เราเลือกใช้
เช่นกันกับรูปแบบการจำกัดจำนวนการแสดง ซึ่งปกติ เราสามารถกำหนดในคำสั่ง SQL ได้เลย แต่เพื่อให้รองรับ
กับการทำงานหลายๆ platform เราควรเลือกใช้คำสั่ง selectLimit() กรณีมีการแบ่งหรือกำหนดขอบเขตข้อมูล
ที่จะแสดง ตามการใช้งานดังนี้
 
$sql = "SELECT province_id,province_name FROM tbl_provinces ";
$result = $db->selectLimit($sql,10,0);
 
    เรากำหนด limit ที่ 10 และ offset เริ่มต้นที่ 0 นั่นคือแสดง 10 รายการแรก
    ตัวแปร $result ที่ได้ จะเป็น result object จะไม่ใช้ array ข้อมูล ดังนั้น เราต้องทำการวนลูปด้วยคำสั่ง
while() เพื่อแสดงข้อมูล ดูตัวอย่าง
 
$sql = "SELECT province_id,province_name FROM tbl_provinces ";
$result = $db->selectLimit($sql,10,0);
if($result){
    while($row = $result->fetchRow()){
        echo $row['province_name']."<br>";
    }
}
 
 

    getRow()

    ใช้สำหรับแสดงข้อมูลแถวแรกของรายการ คืนค่าเป็น array ข้อมูล ตัวอย่างการใช้งาน
 
$sql = "SELECT province_id,province_name FROM tbl_provinces WHERE province_id=1 ";
//$sql = "SELECT province_id,province_name FROM tbl_provinces ";
$row = $db->getRow($sql);
if($row){
    echo $row['province_name'];
}
 
 

    execute()

    ใช้สำหรับรันคำสั่ง SQL ตามที่เรากำหนด โดยจะคืนค่าเป็น result object กรณีเป็นการ SELECT หรือ
แสดงข้อมูล และคืนค่าเป็นค่า boolean ค่า true หรือ false กรณีเป็นการ INSERT หรือ UPDATE หากทำ
คำสั่งสำเร็จ หรือไม่สำเร็จตามลำดับ ดูตัวอย่างการใช้งาน
 
$sql = "SELECT province_id,province_name FROM tbl_provinces ";
$result = $db->execute($sql);
if($result){
    while($row = $result->fetchRow()){ // กรณีต้องการเป็น object ให้ใช้เป็น fetchObj()
        echo $row['province_name'];
    }
}
 
    กรณีเพิ่มข้อมูลใหม่ หรือแก้ไขข้อมูล
 
$sql = "
INSERT INTO tbl_users (name,username,email) 
VALUES ('test','test username','test@localhost.com')
";
if($db->execute($sql)){  // เพิ่มข้อมูลสำเร็จ
    echo "Data Inserted";
    $lastId = $db->insert_Id(); // ได้ค่า id ที่เพิ่มล่าสุด
}

$sql = "
UPDATE tbl_users SET 
name='edit test'
WHERE id=1
";
if($db->execute($sql)){ // แก้ไขข้อมูลสำเร็จ
    echo "Data Updated";
    echo $db->affected_rows(); // ได้จำนวนแถวที่แก้ไขล่าสุด
}
 
    การแก้ไขข้อมูล ค่า $db->affected_rows() จะไม่เท่ากับ 0 หากข้อมูลที่อัพเดท ไม่เป็นค่าเดิม
นั่นคือ ถึงจะทำการอัพเดทผ่าน แต่ถ้าข้อมูลเป็นค่าเดิม คำสั่ง affected_rows() จะเท่า 0 เสมอ เพราะ
ถือว่าข้อมูลไม่มีการเปลี่ยนแปลง
    นอกจากนี้คำสั่ง affected_rows()  ยังใช้ได้กับการ DELETE ข้อมูลด้วย
    เราสามารถกำหนดการ bind variable หรือการกำหนดค่าข้อมูลตัวแปร ที่จะใช้งานในคำสั่ง SQL 
โดยจะแทนที่เครื่องหมายที่เรากำหนดจุดไว้ ในที่นี้ใช้เป็น ?  ตัวแปรจะกำหนดเป็น array และต้องมี
สมาชิกของ array ตามจำนวนที่กำหนดเครื่องหมาย ? 
    การใช้งาน Bind Variable จะช่วยป้องกันในเรื่องของ SQL Injection ดูตัวอย่างประกอบ
 
$bindVars = [1,10];
$sql = "
SELECT province_id,province_name FROM tbl_provinces 
WHERE province_id=? AND province_code=?
";
$result = $db->execute($sql, $bindVars);
if($result){
    while($row = $result->fetchRow()){
        $row['province_name'];
    }
}
 
 

    autoExecute()

    เป็นคำสั่งสำหรับใช้งานการ INSERT หรือ UPDATE ข้อมูลโดยจะสร้างรูปแบบคำสั่ง SQL ให้อัตโมนัติ
ตามรูปแบบการใช้งาน ดูตัวอย่างประกอบ
 
    กรณีเพิ่มข้อมูลใหม่
 
$table = 'tbl_users';
$data["name"] = "Smith";
$data["username"]  = "Smith";
$data["email"]  = "Smith@localhost.com";

$result = $db->autoExecute($table,$data,'INSERT'); // เพิ่มข้อมูลใหม่
if($result){
    echo "Data Inserted";
    echo $db->insert_id();
}
// จะได้ชุดคำสั่ง SQL เป็น
// "INSERT INTO tbl_users (name,username,email) 
// values ('Smith',Smith','Smith@localhost.com')";
 
    กรณีแก้ไขข้อมูล
 
$table = 'tbl_users';
$data["name"] = "Smith";
$data["username"]  = "SmithEdit";
$data["email"]  = "Smith@localhost.com";
$where = "id = '2' ";

$result = $db->autoExecute($table,$data,'UPDATE',$where);
if($result){
    echo "Data Updated";
    echo $db->affected_rows();
}
// จะได้ชุดคำสั่ง SQL เป็น
// "UPDATE tbl_users SET 
// name = 'Smith',
// username ='Smith',
// email = 'Smith@localhost.com' WHERE id = '2' ";
 
    เราสามารถกำหนดรูปแบบของฟิลด์ในตารางผ่านตัวแปร $ADODB_QUOTE_FIELDNAMES โดยกำหนด
ไว้ก่อนบรรทัด $table ตัวอย่างเช่น
 
$ADODB_QUOTE_FIELDNAMES = 'NATIVE';
$table = 'tbl_users';
$data = [
    'name' => 'Smith',
    'username' => 'Smith',
    'email' => 'Smith@localhost.com'
];

$result = $db->autoExecute($table,$data,'INSERT'); // เพิ่มข้อมูลใหม่
// จะได้ชุดคำสั่ง SQL เป็น
// "INSERT INTO `tbl_users` (`name`,`username`,`email`) 
// values ('Smith',Smith','Smith@localhost.com')";
 
    ตัวแปร $ADODB_QUOTE_FIELDNAMES รองรับรูปแบบค่าดังนี้
 
ค่าที่กำหนด	ผลลัพธ์
false		SELECT field_name FROM table
true		SELECT `field_name` FROM table
UPPER		SELECT `FIELD_NAME` FROM table
LOWER		SELECT `field_name` FROM table
NATIVE		SELECT `Field_Name` FROM table
 
    กรณีเป็นการอัพเดทข้อมูลพร้อมกันหลายๆ แถว ควรใช้คำสั่ง execute() แทน autoExecute() เพราะ
ได้ประสิทธิภาพในเรื่องของความเร็วได้ดีกว่า
 
 

    replace()

    ใช้สำหรับการเพิ่มข้อมูลหรือแทนที่ข้อมูลเดิม ทำงานได้ครั้งและ 1 แถวรายการ อาจจะคล้ายคำสั่ง
autoExecute() แต่ก็มีส่วนที่ต่างกันพอสมควร คำสั่ง replace() นี้ไม่เหมือนกับรูปแบบการทำงานของ
คำสั่ง replace ของ MySQL ที่มีการทำงานเป็น insert-delete-duplicate แต่รูปแบบคำสั่งนี้เป็นลักษณะ
update-insert หรือก็คือเพิ่มหรือแก้ไขข้อมูล แล้วแต่กรณี ไม่มีการลบแล้วเพิ่มรายการใหม่
    ดูตัวอย่างการใช้งาน
 
$table = 'tbl_users';
$indexColumn = 'id';
$data = [
    'name' => "'Lisa'",
    'username' => "'Lisa'",
    'email' => "'Lisa@localhost.com'"
];

$result = $db->replace($table,$data,$indexColumn);
if($result==2){ 
    echo "Data Inserted";
    echo $db->insert_id();
}
 
    ตัวแปร $result หรือค่าที่คืนกลับมาจะมีด้วยกัน 3 ค่า คือ 0 = fail, 1 = update, 2 = insert
    ตัว parameter หลักๆ ที่เรากำหนดจะมี ชื่อตาราง สำหรับ indexColumn คือฟิลด์ที่เป็น primary key
หรือฟิลด์ข้อมูลอื่นๆ ที่เราต้องการตรวจสอบ การกำหนดค่า string ของข้อมูล เราจะต้องกำหนด qoute
ด้วยตัวเอง ไม่อย่างนั้นคำสั่งจะไม่ทำงาน  เช่น ถ้าเราใช้ค่าเป็น 'Lisa' จะไม่ทำงานให้กำหนดเป็น "''Lisa'"
แทน มาดูกรณีการแก้ไข
 
$table = 'tbl_users';
$indexColumn = 'id';
$data = [
    'id' => 3,
    'name' => "'Lisa Edit'",
    'username' => "'Lisa'",
    'email' => "'Lisa@localhost.com'"
];

$result = $db->replace($table,$data,$indexColumn);
if($result==1){ 
    echo "Data Updated";
    echo $db->affected_rows();
}
 
    ในส่วนของการแก้ไข ข้างต้น เรากำหนด id ที่จะแก้ไขเป็นเท่ากับ 3 ซึ่งหากมี id เท่ากับ 3 อยู่ ก็จะ
เป็นการแก้ไขข้อมูลของ id นั้น แต่ถ้า id = 3 ไม่มีข้อมูล หรือถูกลบไปแล้ว ก็จะเป็นการ เพิ่มข้อมูลใหม่
ที่มี id เท่ากับ 3 เข้าไปแทน
    การอัพเดทกรณีใช้คำสั่งนี้ จะมีผลให้ค่า affected_rows() มีค่าเป็น 1 เสมอ ถึงแม้ว่าจะเป็นข้อมูลเดิม
แตกต่างจากรูปแบบการอัพเดทปกติ ที่ถ้าหากเป็นข้อมูลเดิม ค่าจะเป็น 0
 
 

    recordCount()

    ใช้สำหรับนับจำนวนรายการที่แสดงทั้งหมด โดยจะเรียกใช้งานผ่าน result object หรือจะเรียก 
recordset object ก็ได้ รูปแบบก็จะประมาณนี้
 
$sql = "SELECT province_id,province_name FROM tbl_provinces ";
$total = $result->recordCount();
echo $total; // จำนวนราการทั้งหมด 77 รายการ
if($result){
    while($row = $result->fetchRow()){ // กรณีต้องการเป็น object ให้ใช้เป็น fetchObj()
        echo $row['province_name'];
    }
}
 
    สามารถใช้เป็นคำว่า rowCount() แทนได้
 
 

    errorMsg()

    ใช้สำหรับแสดงข้อความ error ที่เกิดจากการทำคำสั่งคิวรี่ต่างๆ แล้วมีข้อผิดพลาดเกิดขึ้น ดูตัวอย่าง
สมมติ เรากำหนดชื่อฟิลด์ที่ไม่มีอยู่จริง ก็จะแสดงประมาณนี้
 
$sql = "SELECT provinceID FROM tbl_provinces";
$result = $db->execute($sql);
if(!empty($e = $db->errorMsg())){
    die($e);  // Unknown column 'provinceID' in 'field list'
};
if($result){
    while($row = $result->fetchRow()){ // กรณีต้องการเป็น object ให้ใช้เป็น fetchObj()
        echo $row['province_name'];
    }
}
 
 
    เนื้อหาเบื้องต้น สำหรับการใช้งาน ADOdb ที่จะมาช่วยให้เราสามารถใช้งาน PHP ร่วมกับ Database
platform ต่างๆ ได้สะดวก และไม่จำเป็นต้องปรับแต่งโค้ดใหม่ทั้งหมด หากเปลี่ยนไปใช้งาน Databasse
อื่นๆ ที่รองรับ  เพียงแค่เราเปลี่ยนหรือกำหนด driver ที่ใช้งาน และปรับแต่งค่าเล็กน้อย ก็สามารถใช้งาน
ได้แล้ว จะเห็นมีประโยชน์มาก หากเรากำลังมองหาวิธีการหรือ solution กรณีแบบนี้อยู่
    หวังว่าเนื้อหานี้จะเป็นแนวทาง และเป็นตัวเลือกที่น่าสนใจสำหรับนำไปปรับใช้งาน


   เพิ่มเติมเนื้อหา ครั้งที่ 1 วันที่ 28-09-2020


คำสั่งจัดการความถูกต้องข้อมูลที่นำเข้า และความปลอดภัย

    เนื้อหาเพิ่มเติมนี้ เราจะมาดูเกี่ยวกับการจัดการรูปแบบของข้อมูล ที่จะนำมาใช้งานร่วมกับ
คำสั่ง SQL รวมถึงการป้องกัน SQL Injection
 
    ปกติแล้ว รูปแบบการกำหนด String คำสั่ง SQL เราจะใช้เป็น double qoute (" ") ในลักษณะดังนี้
 
$sql = " SELECT province_id FROM tbl_provinces ";
 
    ในการใช้งานข้อมูลที่เป็นแบบ String เราต้องกำหนด qoute เพิ่มเติมเข้าไปในลักษณะดังนี้
 
$sql = " 
SELECT province_id FROM tbl_provinces 
WHERE province_name LIKE 'กรุงเทพ'
";
 
    สมมติเรากำหนดค่าในตัวแปร ในลักษณะ ดังนี้
 
$string = "กรุงเทพ";
$sql = " 
SELECT province_id FROM tbl_provinces 
WHERE province_name LIKE '$string'
";
 
    ถ้าสมมติค่าตัวแปร เรากำหนดเป็นข้อมูลที่ยังไม่ได้ทำการ escape ในรูปแบบดังนี้
 
$string = "Patrick O'Reilly";
 
    ข้อมูลจะถูกแทนที่ในรูปแบบเป็น
 
SELECT province_id FROM tbl_provinces 
WHERE province_name LIKE 'Patrick O'Reilly'
 
     ทำให้รูปแบบของข้อมูลที่นำไปใช้ ส่งผลให้รูปแบบคำสั่ง SQL ไม่ถูกต้อง และยังมีความเสี่ยงกรณี
ถูกเล่นงานด้วย SQL Injection อีกด้วย 
    มาดูคำสั่งที่ใช้ในการแก้ปัญหาต่างๆ นี้
 
 

    qStr()

    ใช้สำหรับ escape ข้อความ string พร้อมกับเปิด / ปิดครอบด้วยเครื่องหมาย single qoute คำสั่งนี้
เวลาเราเรียกใช้งานร่วมกับคำสั่ง SQL เราไม่ต้องกำหนด single qoute เข้าไปด้วยก็ได้ 
 
$string = "Patrick O'Reilly";
$qString = $db->qStr($string); // ได้ค่าเป็น 'Patrick O\'Reilly'
$sql = " 
SELECT province_id FROM tbl_provinces 
WHERE province_name LIKE $qString
";
// SELECT province_id FROM tbl_provinces 
// WHERE province_name LIKE  'Patrick O\'Reilly'
 
    ถ้าใช้งานกับ MySQLi ก็เหมือนการใช้งานคำสั่ง real_escape_string()  
 
 

    addQ()

    จะคล้ายกับคำสั่ง qStr() เพียงแต่ไม่มีการเพิ่ม single qoute หน้าและหลังให้ ดังนั้นตอนเรียกใช้งานใน
คำสั่ง SQL เราต้องกำหนด single qoute เข้าไปก่อนใช้งานตัวแปรในลักษณะ ดังนี้
 
$string = "Patrick O'Reilly";
$qString = $db->addQ($string); // ได้ค่าเป็น Patrick O\'Reilly
$sql = " 
SELECT province_id FROM tbl_provinces 
WHERE province_name LIKE '$qString'
";
// SELECT province_id FROM tbl_provinces 
// WHERE province_name LIKE  'Patrick O\'Reilly'
 
    คำสั่งนี้มักจะใช้งานร่วมกับการ Bind Variable จะได้ดูตัวอย่างการใช้งานในลำดับต่อไป
 
 

    param()

    ในการใช้งานคำสั่ง execute() ถ้าเราใช้งาน Bind Variable ก็จะกำหนดตัวแปร array ของข้อมูลที่จะส่ง
ไปแทนค่าเครื่องหมาย ? ในคำสั่ง SQL ซึ่งถ้าสมาชิกของตัวแปรมีจำนวนมาก เราอาจจะไม่สะดวกที่จะจำ
ตำแหน่งของ ตัวแปรนั้นๆ ดูตัวอย่างทบทวน
 
$bindVars = [1,10];
$sql = "
SELECT province_id,province_name FROM tbl_provinces 
WHERE province_id=? AND province_code=?
";
$result = $db->execute($sql, $bindVars);
 
    เราสามารถนำคำสั่ง param() มาช่วยแก้ปัญหาได้ ดังนี้
 
$id = $db->param('id');
$code = $db->param('code');
$bindVars = [
    'id'=> 1,
    'code'=> 10
];
$sql = "
SELECT province_id,province_name FROM tbl_provinces 
WHERE province_id=$id AND province_code=$code
";
$result = $db->execute($sql, $bindVars);
 
    การกำหนด param() ก็เหมือนการระบุตำแหน่งที่ข้อมูลจากตัวแปร จะถูกแทนที่เข้าไปในคำสั่ง SQL
จากเดิมที่เรารู้แค่เป็นเครื่องหมาย ? และจะรู้ว่าใช้กับตัวแปรอะไร ก็ต้องไล่ลำดับตำแหน่งเอา
    แต่การกำหนดลักษณะนี้เราสามารถปรับตำแหน่งของ key ในตัวแปร $bindVars ก่อนหลังได้ เช่น
 
$bindVars = [
    'code'=> 10,
    'id'=> 1
];
 
    ทั้งนี้เพราะได้อ้างอิงจากชื่อ ที่กำหนดในขั้นตอนการใช้งานคำสั่ง param() เรียบร้อยแล้ว
    เราสามารถเพิ่มการจัดการรูปแบบของข้อมูลที่เป็น string เข้าไปในลักษณะนี้ได้
 
$string = "%กรุงเทพ%";
$qString = $db->addQ($string);

$p1 = $db->param('name');
$p2 = $db->param('id');
$bindVars = [
    'id' => 1,
    'name'=> $qString
];
$sql = "
SELECT province_id FROM tbl_provinces
WHERE province_name LIKE $p1 AND province_id = $p2
";
$result = $db->execute($sql,$bindVars);
 
 

    prepare()

    ใช้สำหรับใช้งานคำสั่ง SQL ในรูปแบบ prepared statement สามารถศึกษาเพิ่มเติมได้ที่บทความ
ตามลิ้งค์ด้านล่าง
    การใช้งาน MySQL ในรูปแบบ Prepared Statement เบื้องต้น http://niik.in/927 
    
    คำสั่งนี้จะใช้งานได้เฉพาะ database platform ที่รองรับเท่านั้น เช่น MySQL Oracle เป็นต้น
    หาก server ไม่รองรับ ตัวคำสั่งจะคืนค่ากลับมาเป็นรูปแบบคำสั่ง SQL ที่มีเครื่องหมาย ? ในลักษณะ
คล้ายรูปแบบการ BindVariable แทน และถ้ารูปแบบคำสั่ง SQL ที่ใช้งานไม่ถูกต้องหรือไม่รองรับ 
ก็จะคืนค่าเป็น false เป็นต้น 
    ดูตัวอย่างการกำหนดใช้งาน
 
$string = "%กรุงเทพ%";
$qString = $db->addQ($string);
$bindVars = [$qString, 1];

$stmt = $db->prepare("
SELECT province_id FROM tbl_provinces
WHERE province_name LIKE ? AND province_id = ?
");
$result = $db->execute($stmt,$bindVars);


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







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









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











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