Register Register Member Login Member Login Member Login Forgot Password ??
PHP , ASP , ASP.NET, VB.NET, C#, Java , jQuery , Android , iOS , Windows Phone
 

Registered : 109,027

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



 
Clound SSD Virtual Server

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



ติดตามบทความล่าสุดของผู้เขียนได้ที่ phpinfo() Facebook Page



เลิกใช้ฟังก์ชั่น 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)


การสร้าง MySQLi Object ด้วยการ new หรือการสร้า่งด้วย mysqli_init() นั้น
เปรียบเสมือนการจัดหา "โทรศัพท์"




การใช้คำสั่ง 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





การป้องกัน SQL Injection

มาถึงตรงนี้หากใครไม่เข้าใจคำว่า SQL Injection ลองอ่านบทความนี้ดูก่อนนะครับ
สิ่งที่ทุกคนต้องรู้ ในการเขียนโปรแกรมด้วย PHP กับ MySQL หากไม่อยากให้ระบบที่เขียนนั้นถูก HACK ได้ !!!

MySQLi ก็มี method ที่ทำหน้าเหมือนกับ mysql_escape_string() และ mysql_real_escape_string() นั่นก็คือ




MySQLi::real_escape_string()

ใช้ escape ค่าที่ต้องการให้สามารถใช้ใน query ได้อย่างปลอดภัย

MySQLi::real_escape_string($escapestr)
$escapestr ค่าที่ต้องการ escape


ค่าที่คืนกลับมา
string ที่ผ่านการ escape แล้ว


ตัวอย่าง
echo $mysqli->real_escape_string("Cookie's cat");
ผลลัพธ์
Cookie\'s cat


ตัวอย่างการ escape ค่าเืพื่อนำไปใช้ใน query
$_POST['username'] = $mysqli->real_escape_string($_POST['username']); $_POST['password'] = $mysqli->real_escape_string($_POST['password']); $result = $mysqli->query( " SELECT * FROM `users` WHERE `username` = '$_POST[username]' AND `password` = '$_POST[password]' " );


ตัวอย่างการใช้ร่วมกับ sprintf()
$result = $mysqli->query( sprintf( " SELECT * FROM `users` WHERE `username` = '%s' AND `password` = '%s' ", $mysqli->real_escape_string($_POST['username']), // แทนที่ %s ตัวที่ 1 $mysqli->real_escape_string($_POST['password']) // แทนที่ %s ตัวที่ 2 ) );


แต่จะเห็นว่าการเขียนแบบดังกล่าวอาจจะสร้างความรำคาญใจให้กับหลายๆ คน เพราะต้องพิมพ์โค้ดยาวมาก
ดังนั้นเราอาจจะสร้าง method ที่ลดการทำงานเหล่านี้ลงด้วยการ extend คลาส MySQLi

// สร้างคลาสขึ้นมาใหม่โดยขยายคลาส MySQLi class ExtendedMySQLi extends MySQLi { public function __construct($host, $username, $password, $dbname) { // เราจำเป็นต้องเรียก constructor ของคลาสแม่ทุกครั้ง เพื่อให้คลาสลูกทำงานได้อย่างถูกต้อง parent::__construct($host, $username, $password, $dbname); } // ประกาศ method ใหม่ที่เราต้องการ // โดยในที่นี่เราจะสร้าง method ที่สามารถแทนที่ตัวแปรที่ผ่านการ escape แล้วลงใน query // และส่ง query ให้ MySQL Server ในคราวเดียว public function queryf($query) { // ตัวแปรพิเศษที่จะทำให้การทำงานเร็วขึืน ใช้เพื่อเติมเต็ม array ที่จะส่งไปให้ vsprintf // จะได้ไม่เกิด error ในกรณีที่ผู้ใช้กำหนดตัวแปรน้อยกว่าจำนวนตัวแทนที่ใน $query static $fill = array( null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ); $tmp = func_get_args(); // escape ตัวแปรทุกตัว foreach (array_slice($tmp, 1) as $arg) { $args[] = $this->real_escape_string($arg); } return isset($args) // หากมีตัวแปรส่งมา ก็ให้เรียกใช้ vsprintf() เพื่อแทนที่ค่าตัวแปรลงใน query ? $this->query(vsprintf($query, $args + $fill)) // นอกนั้นก็ query ตามปกติ : $this->query($query); } } $mysqli = new ExtendedMySQLi('localhost', 'root', '', 'testdb'); $result = $mysqli->queryf("SELECT '%s'", "Cookie's cat"); $row = $result->fetch_row(); echo $row[0];





บทความที่เกี่ยวข้อง




ติดตามบทความล่าสุดของผู้เขียนได้ที่ phpinfo() Facebook Page







   
Share
Bookmark.   

  By : phpinfo()
  Article : บทความเป็นการเขียนโดยสมาชิก หากมีปัญหาเรื่องลิขสิทธิ์ กรุณาแจ้งให้ทาง webmaster ทราบด้วยครับ
  Score Rating :
  Create Date : 2013-06-04
  Download : No files
Sponsored Links
ThaiCreate.Com Forum


Comunity Forum Free Web Script
Jobs Freelance Free Uploads
Free Web Hosting Free Tools

สอน PHP ผ่าน Youtube ฟรี
สอน Android การเขียนโปรแกรม Android
สอน Windows Phone การเขียนโปรแกรม Windows Phone 7 และ 8
สอน iOS การเขียนโปรแกรม iPhone, iPad
สอน Java การเขียนโปรแกรม ภาษา Java
สอน Java GUI การเขียนโปรแกรม ภาษา Java GUI
สอน JSP การเขียนโปรแกรม ภาษา Java
สอน jQuery การเขียนโปรแกรม ภาษา jQuery
สอน .Net การเขียนโปรแกรม ภาษา .Net
Free Tutorial
สอน Google Maps Api
สอน Windows Service
สอน Entity Framework
สอน Android
สอน Java เขียน Java
Java GUI Swing
สอน JSP (Web App)
iOS (iPhone,iPad)
Windows Phone
Windows Azure
Windows Store
Laravel Framework
Yii PHP Framework
สอน jQuery
สอน jQuery กับ Ajax
สอน PHP OOP (Vdo)
Ajax Tutorials
SQL Tutorials
สอน SQL (Part 2)
JavaScript Tutorial
Javascript Tips
VBScript Tutorial
VBScript Validation
Microsoft Access
MySQL Tutorials
-- Stored Procedure
MariaDB Database
SQL Server Tutorial
SQL Server 2005
SQL Server 2008
SQL Server 2012
-- Stored Procedure
Oracle Database
-- Stored Procedure
SVN (Subversion)
แนวทางการทำ SEO
ปรับแต่งเว็บให้โหลดเร็ว


Hit Link
   







Load balance : Server 03
ThaiCreate.Com Logo
© www.ThaiCreate.Com. 2003-2024 All Rights Reserved.
ไทยครีเอทบริการ จัดทำดูแลแก้ไข Web Application ทุกรูปแบบ (PHP, .Net Application, VB.Net, C#)
[Conditions Privacy Statement] ติดต่อโฆษณา 081-987-6107 อัตราราคา คลิกที่นี่