Technology

[Dev Tip] PDO คืออะไร ?

By Arnon Puitrakul - 15 พฤศจิกายน 2015

[Dev Tip] PDO คืออะไร ?

ช่วงนี้เหมือนหายหน้าหายตาไปสักพักใหญ่ ๆ เลย ตอนนี้เลยต้องเขียนเพื่อทดแทนหน่อยซะแล้ว เข้าเรื่องกันดีกว่า ตอนนี้ตัวผมก็กำลังเรียนวิชา Web Programming อยู่แล้วต้องทำ Project เลยอยากเขียนเรื่องที่ต้องใช้สักหน่อย อย่าง PDO

PDO คืออะไร ?

PDO ย่อมาจาก PHP Data Object ซึ่งมันเอาไว้เชื่อมต่อและทำงานกับฐานข้อมูลได้หลายแบบมาก ๆ ไม่ว่าจะเป็น MySQL หรือ SQLite ที่เราใช้กันบ่อย ๆ ยังเชื่อมต่อกับ ฐานข้อมูลจาก Oracle, ODBC และอื่น ๆ อีกมากมาย ทำให้เราสามารถทำงานกับฐานข้อมูลพวกนี้ได้ยืดหยุ่นมากขึ้น เรียนครั้งเดียวใช้ได้กับ Database หลาย ๆ แบบเลยทีเดียว
ใน PHP นอกจากเราจะใช้ PDO ในการเชื่อมต่อฐานข้อมูล ก็ยังมี mysqli ให้เราได้เลือกใช้ด้วย แต่ความยืดหยุ่นจะไม่เท่ากับ PDO สักเท่าไหร่ และในแง่ของการใช้งานแล้ว PDO สะดวกสบายกว่าเยอะเลย เขียนมันส์กว่าด้วยนะ
ส่วนถ้ากำลังอ่านอยู่แล้ว ถามว่า mysql_sth นี่ทำไมไม่พูดถึง ก็เป็นเพราะว่า มันกำลังจะถูกหิ้วไปแล้วใน PHP เวอร์ชั่นใหม่นี่เอง เพราะฉะนั้นมันถึงเวลาแล้วล่ะครับ ที่จะย้ายมาใช้ PDO กันได้แล้ว

Connect to Database

ในที่นี้ผมขอเชื่อมต่อกับ MySQL ล่ะกันนะครับ เพราะมันน่าจะเป็นอะไรที่ฮิตสุดแล้ว ส่วน DB แบบอื่น ๆ วิธีในการเชื่อมต่อสามารถเข้าไปดูได้ใน Documents ของ PHP นะครับ

$conn = new PDO ("mysql:host=localhost;dbname=Customer_DB","root","");

การเชื่อมต่อก็ไม่ใช่เรื่องยากเลย ให้เราคิดว่า PDO คือ Object ตัวนึงได้เลยที่ Constructor มันต้องการอยู่ 3 อย่างคือ Connection Info, Username, Password ในที่นี้ผมเชื่อมต่อกับ MySQL เลยใส่เป็น mysql ลงไปก่อน และตามด้วย host นั่นคือ localhost
อีกนิดเพื่อความปลอดภัย เราจะดัก Error ด้วย Try Catch สักหน่อยเพื่อความฟรุ้งฟริ้ง

try
{
   $conn = new PDO ("mysql:host=localhost;dbname=Customer_DB","root","");
   echo "Connected to Database";
}
catch (PDOException $e)
{
   echo $e->getMessage();
}

การ Query ข้อมูลจาก Database

การ Query ข้อมูลมาใช้ก็ไม่ยาก ใน PDO เราจะมี Method ที่ชื่อว่า query($command) มาให้เราใช้ โดยให้เราใส่ SQL Statement ลงไป และมันจะ Return กลับมาเป็นผล เทียบได้กับคำสั่ง mysql_query($command); เลย มาลองดูตัวอย่างกันดีกว่า

$conn = new PDO ("mysql:host=localhost;dbname=Customer_DB","root","");

foreach ($conn->query("SELECT * FROM Customer_Info") as $row)
{
   echo $row['name'] . " " . $row['surname'];
}

ลองมาดูที่ยากกันอีกนิด ถ้าเราต้องการอยากรู้ว่าเรา Query ออกมาได้กี่ Row ถ้าเป็น mysql connection แบบเก่าเราก็เรียก mysql_num_rows แต่ใน PDO เราทำแบบด้านล่าง

$conn = new PDO ("mysql:host=localhost;dbname=Customer_DB","root","");
$sqlQuery = $conn->query("SELECT * FROM Customer_Info")->fetchAll();
echo "Number of Row(s) : " . count($sqlQuery);

ก่อนอื่น เราก็ทำการ Connect เข้า Database ตามปกติ จากนั้นเราก็ทำการ Query ข้อมูลขึ้นมา แต่คำสั่ง Query มันจะดึงมาเฉพาะแถวแรกเท่านั้น เราเลยต้องเรียกอีกคำสั่งนึงนั่นคือ fetchAll() มาเพื่อให้มันดึงข้อมูลขึ้นมาทั้งหมด และเมื่อได้แล้ว เราก็จะเรียกคำสั่ง count() เพื่อให้มัน return จำนวน row ออกมานั่นเอง

การ Insert, Update และ Delete

เมื่อกี้ เราก็ได้ Query กันไปแล้ว ถัดมาเราจะมาทำอะไรที่แตกต่างกันนิดหน่อย หลัก ๆ มันคือการ Execute เหมือนกัน แต่ต่างกันตรงที่ Select เราจะได้ข้อมูลกลับมาเป็นข้อมูลที่อยู่ใน Database แต่คำสั่งที่เหลือนั้นไม่ใช่ เราเลยต้องใช้อีกคำสั่งนึงในการทำงาน นั่นคือ exec($command) แทน ส่วนวิธีใช้ก็เหมือนกับ query($command) เลย ลองดูตัวอย่างกัน

$conn = new PDO ("mysql:host=localhost;dbname=Customer_DB","root","");
$conn->exec("INSERT INTO Customer_Info (name,surname,age) VALUES ('Mr.A','B',42)");

แค่นี้ เราก็สามารถที่จะเพิ่มข้อมูลลงไปใน Database ตามที่เราต้องการได้แล้ว โดยคำสั่ง exec($command) มันจะ return ออกมาเป็นตัวเลข บอกว่ามี affected row กี่ row เราสามารถเอาตัวแปรไปรับมาอะไรก็ได้ แล้วแต่เลย
นอกจากนี้ถ้าเรา Insert ข้อมูลลงไป แล้วเราต้องการ ID ที่เป็น PK เรายังสามารถที่จะเรียกอีกคำสั่งนึงเพื่อเอา ID ของ Row ที่ Insert เข้าไปล่าสุดผ่านคำสั่งที่ชื่อว่า lastInsertId(); ได้อีกด้วย

Transaction

ในบางกรณีที่เราต้องทำงานกับการ เพิ่มข้อมูล หรือ สร้างตาราง หรือคำสั่งเยอะ ๆ แล้ว ย่อมมีความผิดพลาดได้ แต่ถามว่า ถ้ามันเกิดขึ้น แล้วเราจะทำยังไง ใน PDO มีวิธีให้แล้ว โดยการทำมันเป็น Transaction ซะเลย

$conn = new PDO ("mysql:host=localhost;dbname=Customer_DB","root","");
try
{
  $conn->beginTransaction();

  $conn->exec ("INSERT INTO Customer_Info(name,surname,age) VALUES ('Mr.A','B',42)");
  $conn->exec ("INSERT INTO Customer_Product_Link (Customer_ID,Product_ID) VALUES (12,11)");

  $conn->commit();
}
catch (PDOException $e)
{
  $conn->rollBack();
  echo $e->getMessage();
}

จาก Code ข้างบน ผมต้องการที่จะ Insert ข้อมูลทั้งหมด 2 ครั้งใน 2 Tables ถ้าเกิดเราเขียนไปแบบปกติ ถ้าเกิดอันใดอันนึงมันเกิดข้อผิดพลาดขึ้นมา เราก็จะต้องมานั่งเขียน Code เพื่อ Delete สิ่งที่เราทำไป แต่ด้วย Feature ใน PDO ที่เรียกว่า Transaction ทำให้เราสามารถ เรียกคืน คำสั่งที่เราสั่งไปได้ทันที โดย Method ที่ชื่อว่า rollBack()

การ Bind Parameter

การ bind parameter คือการแทนที่ตัวแปรใน statement เพื่อประมวลผลต่างๆ ผมว่า เราน่าจะเคย ๆ กันอยู่ เช่นถ้าเราต้องการ SELECT User คนนึงขึ้นมาจากชื่อ ก็น่าจะต้องพิมพ์ว่า

$command = "SELECT * FROM Customer_Info WHERE name = " . $_POST['name'];

อันนี้มันดูเล็กน้อยมาก แต่เมื่อทำงานจริง ๆ แล้วการมานั่งเชื่อม String แบบนี้เยอะ ๆ มันก็ไม่ใช่เรื่องที่สนุกเท่าไหร่เลย และอีกอย่าง มันก็เป็นอีกช่องโหว่หนึ่งของระบบเราที่จะถูกโจมตีด้วย SQL Injection ได้เช่นกัน ไหน ๆ เราก็ใช้ PDO กันมาพอสมควรแล้ว มาดูกับอีก Extention หนึ่งกันนั่นคือ การ Bind Parameter
การ Bind Parameter คือการที่เราแทนที่ตัวแปรตัว Parameter ที่เรากำหนดไว้นั่นเอง ผมเชื่อว่า หลาย ๆ คนที่อ่านน่าจะ งง กันแน่นอน ลองมาดูตัวอย่างกัน

$conn = new PDO ("mysql:host=localhost;dbname=Customer_DB","root","");
$conn->prepare("SELECT * FROM Customer_Info WHERE name = :name");
$conn->exec(Array(:name->$_POST['name']));

ในตอนแรก ถ้าเราต้องการที่จะ Execute คำสั่งเราก็แค่เรียกคำสั่ง exec($command) ก็เป็นอันจบ แต่ถ้าเราต้องการที่จะ Bind Parameter หรืออื่น ๆ เราสามารถเรียกคำสั่ง prepare($command) ทิ้งไว้ก่อนก็ได้ แล้วถ้าเราต้องการให้มัน Execute เราก็แค่เรียกคำสั่ง exec() ได้เลย
ในที่นี้ผมต้องการแทน :name ด้วย $_POST['name'] ก่อนอื่นผมก็ Connect เข้าไปใน Database ตามปกติ ถัดมาผมเรียก prepare() เพื่อเก็บคำสั่งไว้ก่อน และให้มี Bind Parameter ที่ชื่อว่า :name ทิ้งไว้ ทีนี้ พอเราต้องการ Execute เราก็ต้องแทน Parameter ที่เราเหลือทิ้งไว้ให้หมด โดยการอัดมันลง Array ไปเลย แล้วป้อนให้กับ exec() เพื่อให้มัน Execute ออกมาให้เรานั่นเอง
ข้อดีของการ Bind Parameter คือ ง่าย และ ปลอดภัยจาก SQL Injection แน่นอน เพราะว่า การ Bind Parameter มันจะแทนที่ String ของเราด้วย String ที่ผ่านการ Escape String มาให้เรียบร้อยแล้ว นั่นเอง !!

การใช้งานจริง

PDO จริง ๆ แล้วก็ไม่ใช่เรื่องใหม่อะไรเลย เมื่อก่อนผมก็เป็นคนนึงที่ใช้ mysql_sth() ในการทำงานกับ Database อยู่เหมือนกัน ตอนแรก ๆ ที่เปลี่ยนมาใช้ PDO ก็แอบ งง ๆ อยู่เหมือนกัน แต่พอเอาเข้าจริง ๆ การทำงานมันง่ายขึ้นมาก จากเมื่อก่อน ถ้าผมต้องทำงานกับ Database จากหลาย ๆ ค่าย ผมก็ต้องมานั่งเขียนใหม่หลายรอบมา แต่ PDO มันยืดหยุ่นมาก ผมเปลี่ยนแค่บรรทัดเดียวก็จบแล้ว บรรทัดเดียวเปรี้ยวได้นั่นเอง

สรุป

PDO ก็เป็นอีกหนึ่ง Feature นึงที่น่าสนใจมากใน PHP5 ทำให้เราทำงานกับ Database ได้ง่ายขึ้น, รวดเร็วขึ้น และที่สำคัญ ปลอดภัยขึ้นกว่าเดิมเยอะมาก แนะนำเลยให้หันมาลองใช้ PDO เลยล่ะ ตอนนี้คนที่เขียนเว็บ ๆ ก็เยอะแล้วล่ะที่เปลี่ยนมาใช้ PDO เพราะว่าในอนาคตอันใกล้นี้ใน PHP เวอร์ชั่นใหม่ คำสั่ง mysql_sth ที่เราใช้กันมาอย่างเนินนานก็ถึงอันที่ต้อง ลาก๊อย ไปจาก PHP อย่างเป็นทางการ ฉะนั้นเปลี่ยนตอนนี้เถอะครับ ก่อนที่งานจะงอก

Read Next...

ลองกันอีกสักตั้ง iPad Pro ใช้แทนคอมพิวเตอร์ได้มั้ย

ลองกันอีกสักตั้ง iPad Pro ใช้แทนคอมพิวเตอร์ได้มั้ย

เมื่อ 3 ปีก่อน เรามีความพยายามที่จะใช้ iPad Pro เครื่องเดิมแทนคอมพิวเตอร์ ไหน ๆ ตอนนี้เราเปลี่ยน iPad Pro ใหม่แล้ว เราจะมาลองกันอีกสักตั้งว่า เมื่อเวลาผ่านไป มันใช้งานจริงได้มากขึ้นหรือไม่...

ทำไม iPad ยังเป็น iPad ไม่เป็น Mac

ทำไม iPad ยังเป็น iPad ไม่เป็น Mac

ตั้งแต่ iPad Pro M4 และ iPad Air M2 เปิดตัวและเริ่มจำหน่ายออกไป Reviewer หลายคนเริ่มมองเห็นแล้วว่า ปัญหาจริง ๆ ของ iPad ในรอบหลายปีที่ผ่านมา ไม่ได้เกิดจาก iPad แต่เกิดจาก iPadOS บางเจ้าบอกว่า อยากให้เอา macOS มาใส่ด้วยซ้ำ มันยังไงกันนะ วันนี้เราจะมาเล่าประเด็นและความเห็นจากเราให้ให้อ่านกัน...

Microinverter ต่างจาก String Inverter อย่างไร เลือกแบบไหนดีกว่ากัน

Microinverter ต่างจาก String Inverter อย่างไร เลือกแบบไหนดีกว่ากัน

หลังจากเราเขียนเรื่อง Solar Cell ไปมีคนถามเข้ามาอยู่ว่า ถ้าจะเลือกติดตั้ง Solar ระหว่างการใช้ระบบ String Inverter กับ Microinverter เราจะเลือกตัวไหนดี วันนี้เราจะมาเล่าเปรียบเทียบให้อ่านกันว่าแบบไหน น่าจะเหมาะกับใคร...

ทำไมภาษา Programming สมัยใหม่ ถึงไม่มี Pointer Concept

ทำไมภาษา Programming สมัยใหม่ ถึงไม่มี Pointer Concept

ทำไมภาษาบางตัวอย่างภาษา C มี Pointer ในขณะที่ภาษาใหม่ ๆ หลายตัว ไม่มี ทำไมการ Implement Concept หรือเครื่องมือเหล่านี้ถึงไม่ได้รับความนิยม วันนี้เราจะมาเล่าข้อดีข้อเสียของ Feature นี้ในภาษา Programming กัน...