Free Hosting

วันเสาร์ที่ 28 มีนาคม พ.ศ. 2558

เลิกใช้ฟังก์ชั่น mysql_xxxxx() ที่ล้าสมัย (deprecated) และเปลี่ยนมาใช้ MySQLi กันดีกว่า

การใช้ MySQLi แทนการใช้ฟังก์ชั่น mysql_xxxxx() นั้น เขียนได้ 2 แบบคือ
แบบ OOP (เรียกใช้ method ของ object)
กับแบบ Procedural (เรียกใช้ฟังก์ชั่น)

OOP
$result = $mysqli->query("SELECT * FROM `table`");


Procedural
$result = mysqli_query($mysqli, "SELECT * FROM `table`");


ในบทความนี้จะกล่าวถึงแบบ OOP เท่านั้น เพราะการเขียนแบบ OOP นั้นมีโอกาสที่จะเกิดความผิดพลาดน้อยกว่า
เหตุผลคือ การเขียน MySQLi แบบ Procedural จะต้องมีการส่งตัวแปร mysqli object ทุกครั้ง
พูดง่ายๆ คือต้องเขียนยาวกว่า และอาจจะสับสนได้ง่ายกว่า
และอาจจะทำงานช้ากว่า เพราะแบบหลังอาจจะเป็นแค่การเรียก method ของ object ที่ส่งไปในแบบ OOP นั่นเอง

ซึ่งจริงๆ แล้ว mysqli_query() อาจจะทำงานในลักษณะนี้
function mysqli_query(MySQLi $link, $query, $resultmode = MYSQLI_STORE_RESULT) { return $link->query($query, $resultmode); }





การเชื่อมต่อฐานข้อมูลด้วย MySQLi

ก่อนจะใช้ MySQLi นั้น ก็เหมือนกับการใช้ฟังก์ชั่น mysql_xxxxx()
คือต้องเชื่อมต่อกับ MySQL Server ก่อน ซึ่งในแบบเดิมเราใช้ mysql_connect()
แต่ในการเขียนด้วย MySQLi จะทำได้สองแบบ

1. ด้วย MySQLi::__construct() หรือการ new mysqli()
แบบนี้จะสามารถสร้าง MySQLi Object และทำการเชื่อมต่อไปได้ในคำสั่งเดียว

$mysqli = new mysqli('localhost', 'root', 'password', 'default_db_name');
$mysqli = mysqli_connect('localhost', 'root', 'password', 'default_db_name');


2. สร้าง MySQLi Object ด้วย mysqli_init() และเชื่อมต่อด้วย MySQLi::real_connect()
โดย mysqli_init() จะสร้าง MySQLi Object ให้เพื่อเอาไปใช้กับ MySQLi::options() และ MySQLi::real_connect()
ความแตกต่างกับแบบแรกคือ แบบแรกจะไม่สามารถกำหนด options ให้กับการเชื่อมต่อ
เช่น ระยะเวลา timeout, คำสั่ง SQL เริ่มต้น, ตั้งค่าการเชื่อมต่อแบบ SSL ฯลฯ

$mysqli = mysqli_init(); // การปรับแต่ง options ต้องทำก่อนการเชื่อมต่อ $mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 3600); // เชื่อมต่อ $mysqli->real_connect('localhost', 'root', 'password', 'default_db_name');


ดังนั้นในส่วนของการเชื่อมต่อ เราใช้ method/function ดังนี้




MySQLi::__construct()
mysqli_connect()


สร้าง MySQLi Object และเชื่อมต่อฐานข้อมูลไปในคราวเดียว

MySQLi::__construct($host, $username, $password, $dbname) mysqli_connect($host, $username, $password, $dbname)
$host ชื่อหรือ IP ของ MySQL Server เช่น 'localhost' หรือ '127.0.0.1' $username ชื่อผู้ใช้ $password รหัสผ่าน $dbname ชื่อฐานข้อมูล default ที่จะใช้กับทุกๆ query ที่อ่านค่าจากตารางโดยไม่เจาะจงฐานข้อมูล


ค่าที่คืนกลับมา
คืน MySQLi Object กลับมาเสมอ ไม่ว่าผลการเชื่อมต่อจะเป็นอย่างไร ซึ่งหากจะตรวจสอบว่าเชื่อมต่อสำเร็จหรือไม่ ต้องตรวจด้วย MySQLi::$connect_errno หรือ MySQLi::$connect_error


ตัวอย่าง
$mysqli = new mysqli('localhost', 'root', 'password', 'default_db_name'); // หรือ $mysqli = mysqli_connect('localhost', 'root', 'password', 'default_db_name'); if ($mysqli->connect_errno) { echo $mysqli->connect_error; exit; }





mysqli_init()

สร้าง MySQLi Object เพื่อใช้ในการตั้งค่าด้วย MySQLi::options() และเชื่อมต่อด้วย MySQLi::real_connect()

ค่าที่คืนกลับมา
MySQLi Object


ตัวอย่าง
$mysqli = mysqli_init();





MySQLi::real_connect()

เชื่อมต่อฐานข้อมูล โดยต้องเป็น MySQLi Object ที่สร้างขึ้นจาก mysqli_init() เท่านั้น

MySQLi::real_connect($host, $username, $password, $dbname)
$host ชื่อหรือ IP ของ MySQL Server เช่น 'localhost' หรือ '127.0.0.1' $username ชื่อผู้ใช้ $password รหัสผ่าน $dbname ชื่อฐานข้อมูล default ที่จะใช้กับทุกๆ query ที่อ่านค่าจากตารางโดยไม่เจาะจงฐานข้อมูล


ค่าที่คืนกลับมา
true หากเชื่อมต่อสำเร็จ false หากการเชื่อมต่อเกิดความผิดพลาด โดยสามารถตรวจสอบสาเหตุของความผิดพลาดได้ด้วย MySQLi::$connect_error


ตัวอย่าง
$mysqli = mysqli_init(); $mysqli->real_connect('localhost', 'root', 'password', 'default_db_name');





MySQLi::$connect_errno
MySQLi::$connect_error


เป็น property ที่บอกว่า การเรียกใช้ MySQLi::__construct() หรือ MySQLi::real_connect() นั้นมีความผิดพลาดเกิดขึ้นหรือไม่

โดย MySQLi::$connect_errno เป็นตัวเลขของ error code
ส่วน MySQLi::$connect_error จะเป็น error message

หากไม่มี error เกิดขึ้น MySQLi::$connect_errno จะมีค่าเป็น 0
ส่วน MySQLi::$connect_error จะมีค่าเป็น ''

ตัวอย่าง
$mysqli = mysqli_init(); // ใช้ @ ปิดการแสดง warning ไว้ในกรณีที่เราอยากจะแสดง error message ในแบบของเราเอง @$mysqli->real_connect('localhost', 'root', 'password', 'default_db_name'); if ($mysqli->connect_errno) { echo $mysqli->connect_error; exit; }
ผลลัพธ์อาจจะเป็นเช่นนี้
Access denied for user 'root'@'localhost' (using password: YES)





การใช้คำสั่ง SQL

เมื่อเราได้ MySQLi Object จากการเชื่อมต่อฐานข้อมูลที่สำเร็จแล้ว
ก็มาถึงการใช้งาน MySQLi Object นั้นๆ ซึ่งโดยปกติก็คือการส่งคำสั่ง SQL ไปให้ MySQL Server ประมวลผล
ในการเขียนแบบเก่าเราใช้ฟังก์ชั่น mysql_query()
แต่ในแบบใหม่ เราจะใช้ method MySQLi::query() หรือ MySQLi::real_query() และอื่นๆ




MySQLi::query()

ส่งคำสั่ง SQL ไปให้ MySQL Server ประมวลผล

MySQLi::query($query)
$query คำสั่ง SQL ไปให้ MySQL Server ประมวลผล ซึ่งควรจะ escape ด้วย MySQLi::real_escape_string()


ค่าที่คืนกลับมา
false หากเกิดความผิดพลาด ซึ่งสามารถตรวจสอบสาเหตุของความผิดพลาดได้ด้วย MySQLi::$errno และ MySQLi::$error true หากคำสั่ง SQL ที่ส่งไปเป็นคำสั่งที่ไม่คืนผลลัพธ์เป็นข้อมูลกลับมา เช่น INSERT, UPDATE, DELETE ฯลฯ MySQLi_Result Object หากคำสั่ง SQL ที่ส่งไปเป็นคำสั่งที่อ่านข้อมูลกลับมา เ่ช่น SELECT, SHOW, EXPLAIN ฯลฯ


ตัวอย่าง การ INSERT
// escape ค่าที่มาจากผู้ใช้เพื่อป้องกัน SQL Injection $_POST['username'] = $mysqli->real_escape_string($_POST['username']); $_POST['password'] = $mysqli->real_escape_string($_POST['password']); // $result จะเ็ป็น Boolean true หรือ false บอกว่าการ query นั้นๆ สำเร็จหรือไม่ $result = $mysqli->query( " INSERT INTO `users` (`username`, `password`) VALUES ('$_POST[username]', '$_POST[password]') " );
ตัวอย่างการ SELECT
// escape ค่าที่มาจากผู้ใช้เพื่อป้องกัน SQL Injection $_POST['id'] = $mysqli->real_escape_string($_POST['id']); // $result จะเป็น instance ของคลาส MySQLi_Result $result = $mysqli->query("SELECT * FROM `users` WHERE `id` = '$_POST[id]'"); // ซึ่งจะมี method ที่เกี่ยวข้องกับการดึงข้อมูล เทียบเท่ากับฟังก์ชั่นพวก mysql_fetch_xxxxx() $row = $result->fetch_assoc(); // แสดงข้อมูลแถวแรก echo $row['username'];





MySQLi_Result Object

เป็น Object ที่จะได้จากการเรียกใช้ method MySQLi::query() (และอื่นที่คล้ายคลึงกัน)
ซึ่งเป็น Object ที่มี method ในการตรวจสอบและดึงข้อมูล

กระบวนการ query และรับ result นี้ ผมขอเปรียบกับการสั่งซื้อของกับยี่ปั๊วทางโทรศัพท์
ซึ่งการ query คือการโทรไปสั่งซื้อ บอกว่าต้องการอะไร
และ result ที่ได้รับกลับคืนมาจากการ query นั้น "ยังไม่ใช่สินค้า"
แต่เป็น "รถขนสินค้าและพนักงานยกของ"

// เฮียๆ สั่งเบียร์หน่อย เอาสิงห์ กับช้างนะ รวมๆ กันมา 50 ลังล่ะกัน $result = $mysqli->query( " SELECT * FROM `stock` WHERE `type` = 'beer' AND `brand` IN ('Singha', 'Chang') LIMIT 50 " ); // เปรียบให้ $result คือรถขนสินค้า ที่ตอนนี้บรรทุกเบียร์ที่สั่งไปอยู่เต็มคันรถ // ถามขนขับรถดูซิว่าขนมากี่ลัง ครบมั้ย echo $result->num_rows; // ให้พนักงานขนของช่วยขนเบียร์ลงมาดูสักลังก่อนซิ $item = $result->fetch_assoc(); // โอเค ถูกต้อง ยกมาหมดเลยล่ะกัน $warehouse = array(); // ขนลงมาเรื่อยๆ จนกว่าจะไม่มีของให้คนแล้ว while (($item = $result->fetch_assoc())) { // ยกเบียร์เข้าไปเก็บในโกดังทีละลัง $warehouse[] = $item; } // บอกให้คนขับรถกลับไปได้แล้ว $result->free();





MySQLi_Result::fetch_xxxxx()

เป็น method ที่ใช้ดึงข้อมูลที่ได้มาจากการ query ซึ่งมีหลาย method ด้วยกัน แตกต่างตามชนิดข้อมูลที่คืนมา

MySQLi_Result::fetch_assoc() ข้อมูลที่ได้จะเป็น associative array MySQLi_Result::fetch_row() ข้อมูลที่ได้จะเป็น indexed array MySQLi_Result::fetch_array() ข้อมูลที่ได้จะเป็นทั้ง indexed array และ associative array MySQLi_Result::fetch_object() ข้อมูลที่ได้จะเป็น object


โดยปกติเราจะใช้ MySQLi_Result::fetch_assoc() เป็นหลัก
และไม่ควรใช้ MySQLi_Result::fetch_array() เพราะจะทำให้เปลืองหน่วยความจำโดยใช่เหตุ

ตัวอย่าง MySQLi_Result::fetch_assoc()
$result = $mysqli->query("SELECT * FROM `games`"); $row = $result->fetch_assoc(); print_r($row); // เข้าถึงด้วยชื่อคอลัมน์ในตาราง echo $row['title'];
ผลลัพธ์
Array ( [id] => 1 [released] => 2012-09-20 [title] => Pro Evolution Soccer 2013 [price] => 1090 ) Pro Evolution Soccer 2013


ตัวอย่าง MySQLi_Result::fetch_row()
$result = $mysqli->query("SELECT * FROM `games`"); $row = $result->fetch_row(); print_r($row); // เข้าถึงข้อมูลด้วยลำดับของคอลัมน์ในตาราง echo $row[2];
ผลลัพธ์
Array ( [0] => 1 [1] => 2012-09-20 [2] => Pro Evolution Soccer 2013 [3] => 1090 ) Pro Evolution Soccer 2013


ตัวอย่าง MySQLi_Result::fetch_array()
$result = $mysqli->query("SELECT * FROM `games`"); $row = $result->fetch_array(); print_r($row); // เข้าถึงข้อมูลได้ทั้งสองแบบ echo $row['2']; echo $row['title'];
ผลลัพธ์เป็น array ที่มี key ทั้งสองแบบ แต่ไม่ควรใช้เพราะเปลืองหน่วยความจำ (จะเห็นว่ามีข้อมูลที่ซ้ำกัน)
Array ( [0] => 1 [id] => 1 [1] => 2012-09-20 [released] => 2012-09-20 [2] => Pro Evolution Soccer 2013 [title] => Pro Evolution Soccer 2013 [3] => 1090 [price] => 1090 ) Pro Evolution Soccer 2013Pro Evolution Soccer 2013


ตัวอย่าง MySQLi_Result::fetch_row()
$result = $mysqli->query("SELECT * FROM `games`"); $row = $result->fetch_object(); print_r($row); // ต้องเข้าถึงข้อมูลในแบบ Object echo $row->title;
ผลลัพธ์เป็นชนิด Object
stdClass Object ( [id] => 1 [released] => 2012-09-20 [title] => Pro Evolution Soccer 2013 [price] => 1090 ) Pro Evolution Soccer 2013





MySQLi_Result::free()

ทำลายข้อมูลที่ query มาก่อนหน้า เพื่อคืนหน่วยความจำให้กับระบบ

ในการ query เพื่อให้ได้ MySQLi_Result Object นั้น ทุกๆ ครั้ง MySQL จะต้องเก็บผลลัพธ์ที่ได้ไว้ใน buffer ก่อน
ซึ่งอาจจะเป็นในหน่วยความจำ (RAM) หรือในฮาร์ดดิสก์
หลังจากนั้นจึงให้ผู้ใช้อ่านข้อมูลด้วย method fetch_xxxxx() ตามที่กล่าวมาข้างต้น
ซึ่ง buffer ที่ว่านี้จะยังคงอยู่ และยังคงกินทรัพยากรระบบ
จนกว่าจะมีการเรียก method นี้ หรือจนกว่าโปรแกรม PHP จะจบการทำงาน

ดังนั้นเราควรเรียกใช้ method นี้ทุกครั้งเมื่ออ่านข้อมูลออกมาจนครบ หรือไม่ต้องการอ่านข้อมูลจาก MySQLi_Result Object นั้นๆ แล้ว

ตัวอย่าง
$result = $mysqli->query("SELECT * FROM `games`"); while (($row = $result->fetch_assoc())) { // do something } $result->free();





MySQLi_Result::$num_rows

จำนวนแถวที่อยู่ในผลลัพธ์

ตัวอย่าง MySQLi_Result::fetch_row()
$result = $mysqli->query("SELECT * FROM `games` LIMIT 10"); echo $result->num_rows;
ผลลัพธ์
10



1 ความคิดเห็น:


พื้นที่โฆษณา

Free Hosting

พื้นที่โฆษณา

Free Hosting
 

Copyright © สอนเขียนโปรแกรม html php css Java SQL jQuery XML Ajax Design by ScriptMasterWebDesign | Theme by ScriptMasterWebDesign | Powered by HosTing