ทำความรู้จักกับ SQL Layer ของ phpBB
5 Jun
เชื่อว่าบางคนที่เคยทดลองเขียน Web Appication กับฐานข้อมูลมากกว่า 1 ยี่ห้อ น่าจะเคยประสบปัญหานี้กันมาบ้างพอสมควร
ตัวอย่างเช่น สมมติว่าเราจะเขียน PHP เพื่อเรียกดูข้อมูลจาก MySQL เราจะทำตามขั้นตอนต่อไปนี้
- เชื่อมต่อกับฐานข้อมูลด้วย mysql_connect หรือ mysql_pconnect
- เลือกฐานข้อมูลด้วย mysql_select_db
- ส่ง query ไปประมวลผลด้วย mysql_query
- เรียกดูข้อมูลทีละ row ด้วย mysql_fetch_array, mysql_fetch_assoc หรือ mysql_fetch_row หรืออะไรก็ตาม แล้ววนลูป
ถ้าเปลี่ยนมาเขียน PHP (ผู้เขียนเขียน .NET กับ jsp ไม่เป็นครับ เห็นใจหน่อยละกัน) เพื่อเรียกข้อมูลจาก Oracle จะมีขั้นตอนต่อไปนี้
- เชื่อมต่อกับฐานข้อมูลด้วย oci_connect
- เตรียมประมวลผล query ด้วย oci_parse
- ประมวลผลด้วย oci_execute
- เรียกดูข้อมูลด้วย oci_fetch_array
จะเห็นว่ามี 4 ขั้นตอนเหมือนกันก็จริง แต่แต่ละขั้นตอนกลับต่างกัน เช่น
กรณีของ MySQL: ไม่ต้องมา parse แล้วตามด้วย execute เพราะ mysql_query อย่างเดียวก็เหมือนได้ทำสองขั้นตอนนั้นครบแล้ว
กรณีของ Oracle: ไม่ต้องมีการเลือกฐานข้อมูล (mysql_select_db)
เมื่อเป็นเช่นนี้แล้ว ปัญหาย่อมตามมาแน่่ถ้าเกิดมีคนคิดพิเรนทร์ อยากจะเปลี่ยนจากฐานข้อมูลยี่ห้อหนึ่งไปใช้อีกยี่ห้อหนึ่ง
และอีกปัจจัยหนึ่งคือ CMS บางยี่ห้อ เช่น phpBB มีข้อได้เปรียบคือ สามารถใช้งานกับฐานข้อมูลได้หลายๆ ยี่ห้อ
ดังนั้นคงจะไม่ดีแน่ที่จะให้มาเขียนโปรแกรมเดียวกันออกเป็นหลาย copy เพื่อให้สามารถใช้งานกับโปรแกรมฐานข้อมูลหลายๆ ตัว
แนวคิดเกี่ยวกับ sql layer ก็มีแนวคิดคล้ายๆ กับเรื่อง virtual machine แหละครับ
คือ sql layer จะเป็น layer ที่ซ่อนความแตกต่างระหว่างฐานข้อมูลแต่ละยี่ห้อเอาไว้ เหมือนกับที่โปรแกรมภาษาจาวาสามารถรันได้บน JVM โดยที่ไม่ต้องคำนึงว่าอยู่บน OS อะไร
SQL Layer ของ phpBB เป็นโอเพนซอร์สครับ สามารถดาวน์โหลดมาศึกษาดูได้จากการดาวน์โหลด phpBB (SQL Layer ของphpBB3 ถูกเขียนขึ้นมาใหม่ ซึ่งแตกต่างจาก phpBB2 ในที่นี้ขอใช้ phpBB2)
ไฟล์ที่เกี่ยวข้องกับ SQL Layer จะอยู่ใน /phpBB2/db ครับ
เมื่อ ลองเปิดดูแต่ละไฟล์ (เช่น db2.php, msaccess.php, mssql.php, mysql.php, oracle.php, ฯลฯ) จะพบว่าชื่อฟังก์ชันแต่ละฟังก์ชันภายในคลาส sql_db ของแต่ละไฟล์ จะตรงกันหมด ต่างกันที่การทำงานภายในฟังก์ชันเท่านั้น
ขอแนะนำฟังก์ชันที่ใช้กันบ่อยๆ แล้วกันครับ
- sql_db เป็น constructor การเปิดการเชื่อมต่อกับฐานข้อมูลรวมทั้งการเลือกกระทำกับฐานข้อมูลใดฐาน ข้อมูลหนึ่ง จะเกิดขึ้นจากการเรียกฟังก์ชันนี้
- นอกจากนี้ ในกรณีที่เราต้องการ manipulate ข้อมูลที่เป็นภาษาไทย ก็สามารถเข้ามาแก้ไขโค้ดได้ที่ฟังก์ชันนี้ครับ (ว่าแต่ แก้จากข้างนอกดีกว่ามั้ง)
- sql_query สำหรับผู้ที่คุ้นเคยกับ mysql ฟังก์ชันนี้ทำหน้าที่เหมือนกับฟังก์ชัน mysql_query ครับ
- sql_fetchrow เป็นฟังก์ชันที่ดึงข้อมูลที่ได้จากฟังก์ชัน sql_query มาแสดงทีละแถว
- sql_numfields คืนค่าจำนวนฟิลด์ของตาราง
- sql_numrows คืนค่าจำนวนแถว
ขอแสดงตัวอย่างการใช้งานโดยเปรียบเทียบกับสคริปต์ที่เขียนปกติโดยไม่ใช้เครื่องมือตัวนี้ (กับฐานข้อมูล MySQL)
//กรณีที่ไม่ใช้ sql_db
<?php
$link = mysql_connect(‘mysql_host’, ‘mysql_user’, ‘mysql_password’)
or die(‘Could not connect: ‘ . mysql_error());
mysql_select_db(‘my_database’) or die(‘Could not select database’);
$query = ‘SELECT * FROM my_table’;
$result = mysql_query($query) or die(‘Query failed: ‘ . mysql_error());
while ($line = mysql_fetch_array($result)) {
…
}
mysql_free_result($result);
mysql_close($link);
?>
//กรณีที่ใช้ sql_db
<?php
include(“./db/mysql.php”);
$db = new sql_db(‘mysql_host’, ‘mysql_user’, ‘mysql_password’, ‘my_database’, false);
$query = ‘SELECT * FROM my_table’;
$result = $db->sql_query($query);
while ($line = $db->sql_fetchrow($result)) {
…
}
$db->sql_close();
?>
สังเกต ว่า โค้ดสั้นลง ทั้งนี้เพราะภายในฟังก์ชันของ sql_db มีการจัดการเกี่ยวกับ error ภายในฟังก์ชันอยู่แล้ว เราไม่จำเป็นต้องมา or die(‘error message’) เอาเอง
สุดท้ายนี้ สิ่งที่อยากจะบอกคือ ฟังก์ชัน sql_rowseek ใน oracle.php มันทำงานผิดครับ
ถ้าอยากให้มันทำงานได้ถูกต้อง ลองเข้าไปแก้ไขดูแล้วกัน แก้ไม่เกิน 2 บรรทัด รับรอง ^ ^

Recent Comments