เนื้อหานี้จะมาแนะนำ และศึกษาการใช้งาน 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 กรณีแบบนี้อยู่
หวังว่าเนื้อหานี้จะเป็นแนวทาง และเป็นตัวเลือกที่น่าสนใจสำหรับนำไปปรับใช้งาน