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 > บทความจากสมาชิก > PHP อัพเดท MySQL_Connection เป็น Version 2 ครับ



 
Clound SSD Virtual Server

PHP อัพเดท MySQL_Connection เป็น Version 2 ครับ

อัพเดท MySQL_Connection เป็น Version 2 ครับ
สำหรับผู้ที่เคยใช้ class MySQL_Connection ของผม วันนี้มีเวอร์ชั่นใหม่มาแนะนำครับ แต่ไม่ backward compatibility นะครับ ซึ่งเวอร์ชั่นนี้มีการเปลี่ยนแปลงและปรับปรุงในหลายจุดครับ

1. เพิ่มความสามารถในการใช้ table prefix
ซึ่งจะมีประโยชน์สำหรับคนที่ใช้โฮสต์ที่ไม่ให้สร้างฐานข้อมูลมากกว่า 1 หรือจำกัดจำนวนฐานข้อมูล จึงต้องแบ่งฐานข้อมูลตาม prefix ของตาราง

รูปแบบการแทนที่คือ <ชื่อตาราง>

$mysql->tablePrefix = 'web001_';
$mysql->query("SELECT * FROM <user>");


query ที่ได้จะเป็น

SELECT * FROM `web001_user`


2. เพิ่มการ quote identifier ตามแบบ MS SQL Server
คือใช้ [ชื่อคอลัมน์หรือตารางหรือฐานข้อมูล] เพราะ MySQL ใช้ตัวอักษร ` ในการ quote ซึ่งยากต่อการพิมพ์ด้วยคีย์บอร์ดภาษาไทย คนส่วนมากจึงมักไม่ใช้กันและทำให้เกิดปัญหาเช่น ตั้งชื่อคอลัมน์หรือตารางไปตรงกับคำสงวน (พบบ่อยที่สุดคือคำว่า ORDER) และทำให้ error จนต้องไปแก้ไขโครงสร้างตาราง ซึ่งเป็นการแก้ปัญหาที่ปลายเหตุ

$mysql->query("SELECT * FROM [order] WHERE [from] = '[email protected]'");


query ที่ได้จะเป็น

SELECT * FROM `order` WHERE `from` =  '[email protected]'


3. Auto Connect
แค่สร้าง instance ของ class ขึ้นมา แล้วมันจะ connect ให้เองเมื่อเรียกใช้ method ใดๆ ที่จำเป็นต้องใช้ connection ในครั้งแรก

$mysql = new MySQL_Connection('localhost', 'root', '', 'phpinfo');
// $mysql->connect();
...
...
...
// จะเริ่ม connect ตรงนี้
$value = $mysql->queryValue("SELECT 1");


และเพิ่ม arguments ในการเชื่อมต่อไปอีกสองตัว คือ port และ socket (ตาม mysqli_connect())

$mysql = new MySQL_Connection(
	'localhost',                 // Host
	'root',                      // Username
	'',                          // Password
	'phpinfo',                   // Default Database
	3307,                        // Port
	'/var/run/mysqld/mysql.sock' // Socket
);


4. ตัด class MySQL_Result และตัด method MySQL_Connection::queryResult() ออกไป
และเพิ่ม MySQL_Connection::fetch() และ MySQL_Connection::fetchAll() เข้ามาแทน

จากเดิมถ้าอยากจะค่อยๆ fetch result ออกมา

$result = $mysql->query("SELECT * FROM `user`");
while ($row = $result->fetch()) {
    ...
}
$result->free();


ในเวอร์ชั่นนี้ใช้ Class MySQL เองเป็นตัว fetch

$mysql->query("SELECT * FROM `user`");
while ($row = $mysql->fetch()) {
    ...
}

// run query ต่อไปได้เลยโดยไม่ต้องเรียก free() เพราะจะทำให้อัตโนมัติ
$mysql->query("SELECT * FROM `page`");


5. มี option debug ที่ถ้าเป็น false จะไม่จบการทำงานทันที
แต่จะโยน MySQL_Exception ออกมาให้ดักจับ และเลือกจบการทำงานได้ด้วย MySQL_Exception::debug()

$mysql->debug = false;
try {
	$mysql->query("SELECT * * FROM `user`");
} catch (MySQL_Exception $exception) {
	$exception->debug();
}


6. method MySQL_Connection::query() จะ return ค่าออกมาเป็นจำนวนแถวที่ SELECT ได้ หรือจำนวนแถวที่ UPDATE/DELETE ได้

if ($mysql->query("SELECT * FROM `user`")) {
    while ($row = $mysql->fetch()) {
        // ...
    }
    // กระทำการบางอย่างในกรณีที่มีข้อมูล ...
} else {
    // ไม่มีข้อมูล
}





Methods/Properties


__construct([$host, [$username, [$password, [$db, [$port, [$socket]]]]])

สร้าง instance ของ MySQL_Connection
$host - ชื่อหรือ IP address ของ MySQL Server เช่น 'localhost' หรือ '127.0.0.1'
$username - ชื่อผู้ใช้ MySQL
$password - รหัสผ่าน
$db - default database สำหรับทุกๆ query สามารถเรียก selectDb() เพื่อเปลี่ยนในภายหลังได้
$port - หมายเลข TCP port ที่ใช้ในการเชื่อมต่อ
$socket - Unix Domain Socket file ที่ใช้ในการเชื่อมต่อ

$mysql = new MySQL_Connection('localhost', 'root', '');




connect([$host, [$username, [$password, [$db, [$port, [$socket]]]]])

ทำการเชื่อมต่อกับ MySQL Server
แต่ method นี้ไม่จำเป็นต้องเรียกใช้ในกรณีทั่วไป เพราะการเรียก method อื่นๆ ที่ต้องการ connection จะทำการเรียก method นี้ให้อัตโนมัติ
แต่จะมีประโยชน์ในกรณีที่ต้องการ connect ด้วย config ที่ต่างออกไปจากตอนสร้าง instance

$mysql = new MySQL_Connection('localhost', 'root', '');
$mysql->connect('localhost', 'admin', '1234');




close()

ตัดการเชื่อมต่อกับ MySQL Server เพื่อปล่อย connection ให้ process อื่นได้ใช้งาน
ควรใช้หลังจากแน่ใจว่าจะไม่มีการใช้งาน database อีกแล้ว และ script อาจจะต้องทำงานต่ออีกสักระยะ
เช่นการแสดงผลลัพธ์ด้วย template engine
เพราะถ้าหากไม่เรียก close() การเชื่อมต่อจะยังคงอยู่จนกว่า script จะจบการทำงาน

$mysql->close();
session_write_close();
$smarty->display('index.tpl');




selectDb($db)

กำหนด default database สำหรับทุกๆ query

$mysql->selectDb('phpinfo');




query($query [, $params])

ส่ง SQL Query ไปให้ MySQL Server ประมวลผล และคืนค่าแถวที่ SELECT/UPDATE/DELETE กลับมา

echo $mysql->query("SELECT * FROM `user`");


method นี้มักจะใช้ร่วมกับ fetch() เพื่อค่อยๆ อ่านข้อมูลที่ SELECT ได้ออกมาทีละแถว

if ($mysql->query("SELECT * FROM `user`") > 0) {
	while ($user = $mysql->fetch()) {
		// ...
	}
}




fetch([$columnKey])

อ่านค่าแถวหลังเรียกใช้ query() ออกมาครั้งละ 1 แถว
ถ้าไม่เจอแถวใดใดเลยหรือยังไม่ได้เรียกใข้ query() หรือ query ที่เรียกไม่คืนค่าแถว เช่น UPDATE หรือ DELETE จะคืนค่ากลับมาเป็น null

$mysql->query("SELECT * FROM `user`");
$first = $mysql->fetch(); // แถวที่ 1
$second = $mysql->fetch(); // แถวที่ 2
$third = $mysql->fetch(); // แถวที่ 3




fetchAll([$columnKey [, $indexKey]])

อ่านค่าแถวหลังเรียกใช้ query() ออกมาทั้งหมด
method นี้คืนค่ากลับมาเป็น array เสมอ แม้จะไม่เจอแถวใดๆ เลยก็ตาม
ดังนั้นจึงปลอดภัยที่จะเอาไปใช้กับ foreach หรือ function อื่นๆ ที่ต้องการ argument เป็น array

$mysql->query("SELECT * FROM `user`");
$first = $mysql->fetch();
$second = $mysql->fetch();
$third = $mysql->fetch();




free()

ทำการคืนหน่วยความจำที่ใช้ไปกับ result ที่ได้จากการ query ก่อนหน้า

$mysql->query("SELECT * FROM `user`);
$user1 = $mysql->fetch();
$user2 = $mysql->fetch();
$mysql->free();
$user3 = $mysql->fetch(); // null


ซึ่งปกติเราไม่จำเป็นต้องเรียก method นี้ เพราะ method อื่นๆ เช่น queryAndFetch() หรือ queryAndFetchAll() จะทำการเรียกให้โดยอัตโนมัติ
method นี้มีประโยชน์เฉพาะเวลาเรา SELECT ข้อมูลออกมาจำนวนหนึ่ง และต้องการ fetch() ทีละแถว และทำตัดสินใจเองว่าจะหยุดเมื่อไหร่

$mysql->query("SELECT * FROM `user`");
while ($user = $mysql->fetch()) {
	if ($user['type'] !== 'admin') {
		break;
	}
	$users[] = $user;
}
$mysql->free();




queryAndFetch($query [, $params, [$columnKey]])

ส่ง SQL Query ไปให้ MySQL Server ประมวลผล และคืนค่าแถวแรกที่เจอกลับมา
ถ้าไม่เจอแถวใดใดเลยจะคืนค่ากลับมาเป็น null

$user = $mysql->queryAndFetch(
	"SELECT * FROM `user` WHERE `username` = %s[username], `password` = MD5(%s[password]) LIMIT 1",
	$_POST
);
if (!isset($user)) {
	echo 'user not found or wrong password';
	exit;
}


method จะเรียกใช้ free() ทุกครั้ง ดังนั้นแม้จะมีข้อมูลที่ SELECT เจอมากกว่า 1 จะไม่สามารถดึงข้อมูลมากกว่านั้นได้อีก

$user = $mysql->queryAndFetch("SELECT * FROM `user`");
$nextUser = $mysql->fetch(); // จะเป็น null เสมอ เพราะได้ free() ไปแล้ว




queryAndFetchAll($query [, $params, [$columnKey, [$indexKey]]])

ส่ง SQL Query ไปให้ MySQL Server ประมวลผล และคืนทุกแถวที่เจอกลับมา
method นี้คืนค่ากลับมาเป็น array เสมอ แม้จะไม่เจอแถวใดๆ เลยก็ตาม
ดังนั้นจึงปลอดภัยที่จะเอาไปใช้กับ foreach หรือ function อื่นๆ ที่ต้องการ argument เป็น array

foreach ($mysql->queryAndFetchAll("SELECT * FROM `user`") as $user) {
	// ...
}




queryValue($query [, $params])

ส่ง SQL Query ไปให้ MySQL Server ประมวลผล และคืนฟิลด์แรกของแถวแรกที่เจอกลับมา
มีประโยชน์สำหรับในการอ่านค่า query สั้นๆ เช่น SELECT COUNT(*) หรือ SELECT ROW_COUNT()

$numUsers = $mysql->queryValue("SELECT COUNT(*) FROM `user`");




$insertId

เป็น property ที่คืนค่า auto_increment ของแถวที่ INSERT ไปล่าสุด

$mysql->query(
	"INSERT INTO `user` SET `username` = %s, `password` = MD5(%s)",
	array($_POST['username'], $_POST['password'])
);
echo $mysql->insertId;


หาก query ที่เรียกก่อนหน้าไม่ใช่ INSERT ก็จะ return 0



$affectedRows

เป็น property ที่คืนค่าแถวที่มีผลกระทบจากคำสั่งประเภท UPDATE/DELETE หรือจำนวนแถวที่ SELECT ได้

$mysql->query("DELETE FROM `user`");
echo $mysql->affectedRows;


ซึ่งปกติไม่จำเป็นต้องเรียกใช้ก็ได้ เพราะ query() คืนค่านี้กลับมาให้อยู่แล้ว

echo $mysql->query("DELETE FROM `user`");




$numRows

เป็น property ที่คืนจำนวนแถวที่ SELECT ได้

$mysql->query("SELECT * FROM `user`");
echo $mysql->numRows;


ซึ่งปกติไม่จำเป็นต้องเรียกใช้ก็ได้ เพราะ query() คืนค่านี้กลับมาให้อยู่แล้ว

echo $mysql->query("SELECT * FROM `user`");


จะมีประโยชน์ก็ต่อเมื่อ query ด้วย method อื่น

// แม้จะดึงออกมาแค่แถวแรก แต่จริงๆ MySQL อาจจะ SELECT เจอมากกว่า 1 แถว
$user = $mysql->queryAndFetch("SELECT * FROM `user`");
echo $mysql->query->numRows;




$tablePrefix

prefix ของตารางที่จะเอาไปต่อหน้าการแทนที่ในรูปแบบ <ชื่อตาราง>

$mysql->tablePrefix = 'web001_';
$mysql->query("SELECT * FROM <user>");
// SELECT * FROM `web001_user`




$charset

default charset สำหรับการเชื่อมต่อ
default คือ utf8

$mysql->charset = 'tis620';




$debug

หากเป็น true จะจบการทำงานทุกครั้งที่มี error เกิดขึ้นจากการ connect หรือ query
แต่ถ้าเป็น false จะโยน MySQL_Exception ออกมาให้ดักจับ
default เป็น true
แต่ควรกำหนดเป็น false หากต้องการตรวจจับ error
เช่นในกรณีที่ต้องการตรวจสอบว่ามีข้อมูลซ้ำหรือไม่ก่อน INSERT
เราอาจจะไม่ต้อง SELECT เพื่อตรวจสอบ แต่แค่ INSERT ข้อมูลเข้าไป หากข้อมูลที่ INSERT มันมี UNIQUE KEY ซ้ำ ก็จะมี Exception โยนออกมา

// ทำให้โยน Exception ออกมาหากมี error
$mysql->debug = false;
try {
	// หาก `username` มี index เป็น UNIQUE จะ INSERT ไม่ได้ถ้าข้อมูลที่เข้าไปใหม่ซ้ำกับของเดิม
	$mysql->query(
		"INSERT INTO `user` SET `username` = %s, `password` = MD5(%s)",
		array($_POST['username'], $_POST['password'])
	);
} catch (MySQL_Exception $exception) {
	// ... จัดการกับ error
}




$error
$errno

error message และ error code ของ error ที่เกิดขึ้นล่าสุด
ซึ่ง property ทั้งสองนี้จะไม่มีประโยชน์หาก $debug เป็น true เพราะเมื่อเกิด error จะจบการทำงานก่อนได้อ่านค่าจาก property เหล่านี้
$mysql->debug = false;
try {
	// หาก `username` มี index เป็น UNIQUE จะ INSERT ไม่ได้ถ้าข้อมูลที่เข้าไปใหม่ซ้ำกับของเดิม
	$mysql->query(
		"INSERT INTO `user` SET `username` = %s, `password` = MD5(%s)",
		array($_POST['username'], $_POST['password'])
	);
} catch (MySQL_Exception $exception) {
	// ตรวจสอบ error code ว่าเป็นกรณี KEY ซ้ำหรือเปล่า
	// http://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html#error_er_dup_entry
	if ($mysql->errno === 1062 // ER_DUP_ENTRY
		|| $mysql->errno === 1586 // ER_DUP_ENTRY_WITH_KEY_NAME
	) {
		// ... แจ้งว่าข้อมูลซ้ำ
	} else {
		// error อื่นๆ
	}
}






อธิบาย Arguments ที่ใช้ใน query(), fetch(), fetchAll(), queryAndFetch(), queryAndFetchAll(), queryValue()


$params - ค่าหรือ array ของค่าที่ต้องการแทนที่ใน query

โดยการแทนที่นั้นจะใช้เครื่องหมาย % ตามด้วยอักษร i, s, b, d, f, %
สามารถมี n ต่อท้าย (ยกเว้น %i และ %%) เพื่อกำหนดว่า ค่านี้สามารถเป็น NULL ใน SQL

$mysql->query(
	"SELECT %s, %sn",
	array(null, null)
);
// SELECT '', NULL


และสามารถมี [ชื่อ key] ต่อท้ายเพื่อกำหนดว่าจะใช้ key ไหนใน array $params
หากไม่กำหนด จะเรียงลำดับตั้งแต่ 0 ไปเรื่อยๆ

$mysql->query(
	"SELECT %s, %s[abc], %sn[1000], %s, %s",
	array(
		'Test',
		'PHP',
		'MySQL',
		'abc' => 555,
		1000 => null,
	)
);
// SELECT 'Test', '555', NULL, 'PHP', 'MySQL'


สามารถลดการเขียนโค้ดลงได้ โดยส่ง array ที่มี key แน่ชัดอยู่แล้วเข้าไปเป็น $params โดยตรง

// หาก $_POST มี key $_POST['username'] และ $_POST['password']
// ก็สามารถส่งไปเป็น $params ได้โดยตรง
$mysql->query(
	"
	INSERT INTO `user`
	(`username`, `password`)
	VALUES
	(%s[username], %s[password])
	"
	$_POST
);


หากค่าที่นำมาแทนที่เป็น array ก็จะแปลงให้เป็น list ของค่า (คั่นด้วย ,)
เหมาะสำหรับเอาไปใช้ใน IN (...) หรือ INSERT INTO (...) VALUES (...)

$superUsers = $mysql->queryAndFetchAll(
	"SELECT * FROM `user` WHERE `type` IN (%s)",
	// ต้องเป็น array ซ้อน array มิเช่นนั้นจะถูกมองว่าเป็นค่าเดี่ยวๆ
	// เช่น หากใช้ array('admin', 'vip') แบบนี้ %s จะถูกแทนที่ด้วย 'admin'
	array(
		array('admin', 'vip')
	)
);
// SELECT * FROM `user` WHERE `type` IN ('admin','vip')


$mysql->query(
	"INSERT INTO `user` (%i) VALUES (%s)",
	array(
		array('username', 'password'), // %i list ของ identifier
		array('phpinfo', '1234'), // %s list ของ string
	)
);
// INSERT INTO `user` (`username`, `password`) VALUES ('phpinfo', '1234')





i - แปลงค่าให้เป็น identifier คือครอบด้วย `

$mysql->query("SELECT * FROM %i", 'user');
// SELECT * FROM `user`


ถ้าในค่าที่เอาไปแทนที่มีเครื่องหมาย . ก็จะทำการแยกส่วนให้

$mysql->query("SELECT * FROM %i", 'phpinfo.user');
// SELECT * FROM `phpinfo`.`user`


s - แปลงค่าให้เป็น SQL string ซึ่งจะทำการ escape ค่าให้โดยอัตโนมัติ เพื่อป้องกัน SQL Injection

$mysql->query("SELECT %s", 123);
// SELECT '123'
$mysql->query("SELECT %s", "That's it!!!");
// SELECT 'That\'s it!!!'


d - แปลงค่าให้เป็นเลขจำนวนเต็ม (int)

$mysql->query("SELECT %d", '123.123');
// SELECT 123


f - แปลงค่าให้เป็นเลขจำนวนจริง (float)

$mysql->query("SELECT %f", '123.123');
// SELECT 123.123


b - แปลงค่าให้เป็น SQL boolean คือ TRUE หรือ FALSE

$mysql->query("SELECT %b", 123);
// SELECT TRUE
$mysql->query("SELECT %b", 0);
// SELECT FALSE


% - เอาค่าที่ส่งไปแทนที่ตรงๆ โดยไม่ escape ใดใดทั้งสิ้น ควรใช้อย่างระมัดระวัง

$mysql->query("SELECT %%", "COUNT(*)");
// SELECT COUNT(*)


หากในค่าที่ส่งไปมีสัญลักษณ์การแทนที่อื่นๆ ก็จะทำการแทนที่นั้นแบบ recursive

$mysql->query(
	"SELECT %%",
	array("%d[x] * %d[y]", 'x' => 2, 'y' => 4)
);
// SELECT 2 * 4


เหมาะสำหรับเพิ่มเงื่อนไขแบบ dynamic ให้กับ query

// ถ้ามี $_GET['username'] ส่งมา
if (isset($_GET['username'])) {
	// เพิ่มเงื่อนไข
	$where[] = `username` = %s[username]";
}
// ถ้ามี $_GET['email'] ส่งมา
if (isset($_GET['email'])) {
	// เพิ่มเงื่อนไข
	$where[] = "`email` = %s[email]";
}
$_GET[0] = isset($where)
	? 'WHERE ' . implode(' OR ', $where)
	: '';
$mysql->query("SELECT * FROM `user` %%", $_GET);
/*
สมมติว่าถ้า $_GET['username'] = 'phpinfo' ก็จะได้ query
SELECT * FROM `user` WHERE `username` = 'phpinfo'
แต่ถ้าไม่มีตามเงื่อนไขที่กำหนดก็จะได้ query
SELECT * FROM `user`
*/




$columnKey - ดึงเฉพาะค่าของฟิลด์ที่ต้องการออกมา

โดยปกติการ fetch จะดึงข้อมูลออกมาเป็น array ข้อมูลของแถว แม้ในแถวนั้นๆ จะมีแค่ฟิลด์เดียวก็ตาม

$user = $mysql->queryAndFetchAll("SELECT `username` FROM `user`");
/*
array(
	array('username' => 'phpinfo'),
	array('username' => 'test'),
)
*/


แต่ถ้าเราอยากได้ array เฉพาะค่าของฟิลด์ที่ต้องการ

$users = $mysql->queryAndFetchAll("SELECT `username` FROM `user`", null, 'username');
/*
array(
	'phpinfo',
	'test',
)
*/




$indexKey - กำหนดให้ค่าของฟิลด์ที่ต้องการเป็น key ของ array

โดยปกติการ fetchAll จะดึงข้อมูลออกมาเป็น array ข้อมูลของแถวโดยเรียงลำดับจาก 0 ไปเรื่อยๆ
แต่ถ้าเราอยากให้ array ที่ได้ มี key จากค่าในแถว เราสามาถใช้ $indexKey ช่วยได้

$users = $mysql->queryAndFetchAll("SELECT `username`, `email` FROM `user`", null, null, 'username');
/*
array(
	'phpinfo' => array('email' => '[email protected]'),
	'test' => array('email' => '[email protected]'),
)
*/


ใช้ร่วมกับ $columnKey

$users = $mysql->queryAndFetchAll("SELECT `username`, `email` FROM `user`", null, 'email', 'username');
/*
array(
	'phpinfo' => '[email protected]',
	'test' => '[email protected]',
)
*/



Source Code
<?php
/**
* MySQL_Connection V2
* คลาสที่จะช่วยให้คุณเขียนโปรแกรมเชื่อมต่อกับฐาน MySQL ได้สะดวกและปลอดภัยขึ้น
* Copyright (c) 2014, phpinfo.in.th (http://www.phpinfo.in.th)
*/
class MySQL_Connection
{
	protected static $options = array(
		'mysqli.default_host',
		'mysqli.default_user',
		'mysqli.default_pw',
		null,
		'mysqli.default_port',
		'mysqli.default_socket',
	);

	private $_debug = true;
	private $_tablePrefix = '';
	private $_defaultCharset = 'utf8';
	private $_affectedRows;
	private $_numRows;
	private $args;
	private $c;
	private $r;
	private $s = array();
	private $d;
	private $i;

	public function __construct(
		$host = null,
		$username = null,
		$password = null,
		$db = null,
		$port = null,
		$socket = null
	) {
		$args = array($host, $username, $password, $db, $port, $socket);
		foreach (self::$options as $i => $default) {
			if (!isset($args[$i]) && isset($default)) {
				$args[$i] = ini_get($default);
			}
		}
		$this->args = $args;
	}

	protected function replaceStringCallback($matches)
	{
		if (isset($matches[3])) {
			$nullable = isset($matches[3][1]);
			if (isset($matches[4])) {
				$value = isset($this->d[$matches[4]])
					? $this->d[$matches[4]]
					: null;
			} else {
				$value = isset($this->d[$this->i])
					? $this->d[$this->i++]
					: null;
			}
			if (is_array($value)) {
				switch ($matches[3][0]) {
					case '%':
						return $this->replaceString(implode(',', $value));
					case 'i':
						foreach ($value as &$ref) {
							$ref = implode(
								'`.`',
								explode('.', preg_replace('/`/u', '``', $ref), 3)
							);
						}
						return '`' . implode('`,`', $value) . '`';
					case 'b':
						foreach ($value as &$ref) {
							$ref = $nullable && $ref === null
								? 'NULL'
								: ((bool) $ref ? 'TRUE' : 'FALSE');
						}
						return implode(',', $value);
					case 'd':
						foreach ($value as &$ref) {
							$ref = $nullable && $ref === null
								? 'NULL'
								: (int)$ref;
						}
						return implode(', ', $value);
					case 'f':
						foreach ($value as &$ref) {
							$ref = $nullable && $ref === null
								? 'NULL'
								: (float)$ref;
						}
						return implode(', ', $value);
					case 's':
						foreach ($value as &$ref) {
							$ref = $nullable && $ref === null
								? 'NULL'
								: $this->c->real_escape_string($ref);
						}
						return "'" . implode("','", $value) . "'";
				}
			} else {
				switch ($matches[3][0]) {
					case '%':
						return $this->replaceString($value);
					case 'i':
						return '`'
							. implode(
								'`.`',
								explode('.', preg_replace('/`/u', '``', $value), 3)
							)
							. '`';
					case 'b':
						return $nullable && $value === null
							? 'NULL'
							: ((bool) $value ? 'TRUE' : 'FALSE');
					case 'd':
						return $nullable && $value === null
							? 'NULL'
							: (int)$value;
					case 'f':
						return $nullable && $value === null
							? 'NULL'
							: (float)$value;
					case 's':
						return $nullable && $value === null
							? 'NULL'
							: "'{$this->c->real_escape_string($value)}'";
				}
			}
		} elseif (isset($matches[2])) {
			return "`{$this->_tablePrefix}{$matches[2]}`";
		} elseif (isset($matches[1])) {
			return "`{$matches[1]}`";
		}
		return $matches[0];
	}

	public function connect()
	{
		if (isset($this->c)) {
			return;
		}
		$this->c = mysqli_init();
		$args = func_get_args();
		@call_user_func_array(array($this->c, 'connect'), $args + $this->args);
		if ($this->c->connect_error) {
			$exception = new MySQL_Exception(
				$this->c->connect_error,
				$this->c->connect_errno
			);
			$this->c = null;
			if ($this->_debug) {
				$exception->debug();
			}
			throw $exception;
		}
		$this->c->set_charset($this->_defaultCharset);
	}

	public function selectDb($db)
	{
		$this->connect();
		$this->c->select_db($db);
		if ($this->c->error) {
			$exception = new MySQL_Exception($this->c->error, $this->c->errno);
			if ($this->_debug) {
				$exception->debug();
			}
			throw $exception;
		}
	}

	public function ping()
	{
		$this->connect();
		return $this->c->ping();
	}

	public function close()
	{
		if (!isset($this->c)) {
			return;
		}
		$this->free();
		$return = $this->c->close();
		$this->c = null;
		return $return;
	}

	public function escapeString($value)
	{
		if (!isset($this->c)) {
			$this->connect();
		}
		return $this->c->real_escape_string($value);
	}

	public function replaceString()
	{
		if (!isset($this->c)) {
			$this->connect();
		}
		$args = func_get_args();
		$query = array_shift($args);
		if ($args) {
			if (!isset($args[1])) {
				$args = is_array($args[0]) ? $args[0] : array($args[0]);
			}
			if (isset($this->d)) {
				$this->s[] = array($this->d, $this->i);
			}
			$this->d = $args;
			$this->i = 0;
		}
		$result = preg_replace_callback(
			'/\'(?>\\\\\'|\'\'|[^\']+)*\'|"(?>\\\\"|""|[^"]+)*"|`(?>``|[^`]+)*`|\[([^\s\]]+)\]|\<([^\s\>]+)\>|%(%|i|(?>s|b|d|f)n?)?(?>\[([^\]]+)\])?|%/u',
			array($this, 'replaceStringCallback'),
			$query
		);
		if ($args) {
			if (!empty($this->s)) {
				list($this->d, $this->i) = array_pop($this->s);
			} else {
				$this->d = null;
			}
		}
		return $result;
	}

	public function query($query, $params = null)
	{
		$this->connect();
		$this->free();
		$result = $this->c->query($actualQuery = $this->replaceString($query, $params));
		if ($result === false) {
			$exception = new MySQL_Exception(
				$this->c->error,
				$this->c->errno,
				$query,
				$actualQuery
			);
			if ($this->_debug) {
				$exception->debug();
			}
		}
		if ($result instanceof mysqli_result) {
			$this->r = $result;
			return $this->_numRows = $this->_affectedRows = $this->c->affected_rows;
		}
		$this->_numRows = 0;
		return $this->_affectedRows = $this->c->affected_rows;
	}

	public function queryAndFetch($query, $params = null, $columnKey = null)
	{
		$this->query($query, $params);
		$row = $this->fetch($columnKey);
		$this->free();
		return $row;
	}

	public function queryAndFetchAll($query, $params = null, $columnKey = null, $indexKey = null)
	{
		$this->query($query, $params);
		return $this->fetchAll($columnKey, $indexKey);
	}

	public function queryValue($query, $params = null)
	{
		if ($this->query($query, $params)) {
			$row = $this->fetch();
			$this->free();
			return $row[key($row)];
		}
	}

	public function fetch($columnKey = null)
	{
		if (!isset($this->r)) {
			return;
		}
		if (!($row = $this->r->fetch_assoc())) {
			$this->free();
		} else {
			return isset($columnKey)
				? (isset($row[$columnKey])
					? $row[$columnKey]
					: null)
				: $row;
		}
	}

	public function fetchAll($columnKey = null, $indexKey = null)
	{
		if (!isset($this->r)) {
			return;
		}
		$rows = array();
		if (($row = $this->r->fetch_assoc())) {
			if (isset($columnKey)) {
				if (array_key_exists($columnKey, $row)) {
					if (isset($indexKey) && array_key_exists($indexKey, $row)) {
						do {
							$rows[$row[$indexKey]] = $row[$columnKey];
						} while (($row = $this->r->fetch_assoc()));
					} else {
						do {
							$rows[] = $row[$columnKey];
						} while (($row = $this->r->fetch_assoc()));
					}
				}
			} elseif (isset($indexKey) && array_key_exists($indexKey, $row)) {
				do {
					$rows[$row[$indexKey]] = $row;
				} while (($row = $this->r->fetch_assoc()));
			} else {
				do {
					$rows[] = $row;
				} while (($row = $this->r->fetch_assoc()));
			}
		}
		$this->free();
		return $rows;
	}

	public function free()
	{
		if (!isset($this->r)) {
			return;
		}
		$this->r->free();
		$this->r = null;
	}

	public function __get($name)
	{
		if (isset($this->{$prop = '_' . $name})) {
			return $this->$prop;
		}
		if ($name === 'charset') {
			$this->connect();
			return $this->c->character_set_name();
		}
		static $map = array(
			'error' => 'error',
			'errno' => 'errno',
			'insertId' => 'insert_id',
		);
		if (isset($map[$name])) {
			return $this->c->{$map[$name]};
		}
	}

	public function __set($name, $value)
	{
		if (isset($this->{$prop = '_' . $name})) {
			$this->$prop = $name === 'debug'
				? (bool)$value
				: (string)$value;
		}
		if ($name === 'charset') {
			$this->connect();
			$this->c->set_charset($value);
			if ($this->c->error) {
				$exception = new MySQL_Exception($this->c->error, $this->c->errno);
				if ($this->_debug) {
					$exception->debug();
				}
				throw $exception;
			}
		}
	}
}

class MySQL_Exception extends Exception
{
	public static function formatMessage($message, $width = 100)
	{
		$width = max(40, (int)$width);
		if (!preg_match_all('/^\t+/mu', $message, $matches)) {
			$matches[0][0] = '';
		}
		sort($matches[0]);
		$message = trim(
			preg_replace(
				'/\t/u',
				'    ',
				preg_replace("/^{$matches[0][0]}/mu", '', $message)
			)
		);
		if (preg_match_all("/\\n?(.{0,{$width}})/u", $message, $matches, PREG_SET_ORDER)) {
			foreach ($matches as $match) {
				$lines[] = $match[1];
			}
			return implode("\n", $lines);
		}
		return $message;
	}

	private $sourceQuery;
	private $actualQuery;

	public function __construct($message, $code, $sourceQuery = null, $actualQuery = null)
	{
		parent::__construct((string)$message, (int)$code);
		$this->sourceQuery = $sourceQuery;
		$this->actualQuery = $actualQuery;
	}

	public function getDebugMessage($width = 100)
	{
		$hr = str_repeat('-', $width = max(40, (int)$width));
		return self::formatMessage(
			isset($this->sourceQuery)
				? sprintf(
					"{$hr}\nMySQL error:\n{$hr}\n\n#%s - %s\n\n{$hr}\nSource query:\n{$hr}\n\n%s\n\n{$hr}\nActual query:\n{$hr}\n\n%s\n\n{$hr}\nTrace:\n{$hr}\n\n%s",
					$this->getCode(),
					$this->getMessage(),
					$this->sourceQuery,
					$this->actualQuery,
					$this->getTraceAsString()
				)
				: sprintf(
					"{$hr}\nMySQL error:\n{$hr}\n\n#%s - %s\n\n{$hr}\nTrace:\n{$hr}\n\n%s",
					$this->getCode(),
					$this->getMessage(),
					$this->getTraceAsString()
				),
			$width
		);
	}

	public function debug($width = 100)
	{
		if (!headers_sent()) {
			header('Content-Type: text/plain; charset=utf-8', true);
			while (ob_get_level()) {
				ob_end_clean();
			}
		}
		exit($this->getDebugMessage($width));
	}
}








   
Share
Bookmark.   

  By : phpinfo()
  Article : บทความเป็นการเขียนโดยสมาชิก หากมีปัญหาเรื่องลิขสิทธิ์ กรุณาแจ้งให้ทาง webmaster ทราบด้วยครับ
  Score Rating :
  Create Date : 2014-12-10
  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 04
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 อัตราราคา คลิกที่นี่