|
|
|
ตัวอย่างการใช้ PDO รวมทั้งการดักหาจุดบกพร่องต่างๆโดยละเอียดยิบ |
|
|
|
|
|
|
|
ก่อนหน้านี้เคยเขียนตัวอย่างการใช้ mysqli ไปแล้วในกระทู้นี้ https://www.thaicreate.com/php/forum/095986.html#65
จึงคิดว่าน่าจะเขียนตัวอย่างการใช้ PDO บ้าง เผื่อจะได้เป็นประโยชน์กับคนอื่นๆในอนาคต
ตัวอย่างต่อไปนี้ใช้โครงสร้างฐานข้อมูลแบบง่ายๆเลย
Code (SQL)
DROP TABLE IF EXISTS `people`;
CREATE TABLE IF NOT EXISTS `people` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
`date` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ส่วนตัวอย่างข้อมูลก็ไปหา generate เอาได้ตามเว็บทั่วไป เช่น http://filldb.info/dummy หรือหาได้จากคำว่า generate db
ตัวอย่างการใช้ PDO และการดักผลลัพธ์ต่างๆเพื่อหาจุดบกพร่องโดยละเอียด
Code (PHP)
<?php
$config = [
'dsn' => 'mysql:host=127.0.0.1;dbname=test_generic-tests;charset=utf8mb4',
'username' => 'user',
'passwd' => 'pass',
'options' => [
// ใช้ `\PDO::ERRMODE_SILENT` สำหรับงานจริงหรือ production.
// ใช้ `\PDO::ERRMODE_EXCEPTION` สำหรับขั้นตอน development.
// การใช้ `PDO::ERRMODE_WARNING` จะทำให้ไม่สามารถใช้ `try...catch` ได้.
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
],
];
config.php
Code (PHP)
<?php
require 'config.php';
try {
$PDO = new \PDO($config['dsn'], $config['username'], $config['passwd'], $config['options']);
} catch (\Exception $ex) {
echo 'Error: ' . $ex->getMessage() . ' [Code: ' . $ex->getCode() . ']<br>' . PHP_EOL;
echo $ex->getFile() . ' on line ' . $ex->getLine() . '<br>' . PHP_EOL;
exit();// จบ ไม่ต้องไปต่อ.
}
$title = 'ตัวอย่างการแสดงรายการ โดยใช้ PDO';
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title><?=$title;?></title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1><?=$title;?></h1>
<table>
<thead>
<tr>
<th>id</th>
<th>ชื่อ</th>
<th>ที่อยู่</th>
<th>วันที่</th>
</tr>
</thead>
<tbody>
<?php
$sql = 'SELECT * FROM `people` WHERE `name` LIKE :name ORDER BY `id` DESC LIMIT 0, 20';
try {
// กระบวนการต่อไปนี้เป็นการดักผลลัพธ์แต่ละขั้นตอน เพื่อตรวจอย่างละเอียดว่าได้ค่า return ตรงตามที่ต้องการหรือไม่ เพื่อหาจุดที่ผิดพลาดต่อไป.
// ในงานจริงอาจไม่จำเป็นต้องดักทุกขั้นตอนแบบนี้เพราะจะสิ้นเปลืองทรัพยากร cpu, memory.
$sth = $PDO->prepare($sql);
unset($sql);// $sql ไม่ใช้แล้ว unset ทิ้งไป เพื่อคืนพื้นที่ให้หน่วยความจำ
if (!$sth instanceof \PDOStatement) {
// ถ้า prepare สำเร็จจะต้องได้ค่าเป็น PDOStatement เท่านั้น
// อ้างอิง https://www.php.net/manual/en/pdo.prepare.php
$error = $PDO->errorInfo();
throw new \Exception('SQL state[' . $error[0] . ']: ' . $error[2], $error[1]);
}
$bindResult = $sth->bindValue(':name', '%t%', \PDO::PARAM_STR);
if (false === $bindResult) {
// ถ้าการ bindValue ไม่สำเร็จมันจะได้ค่าเป็น false.
// อ้างอิง https://www.php.net/manual/en/pdostatement.bindvalue.php
$error = $sth->errorInfo();
throw new \Exception('SQL state[' . $error[0] . ']: ' . $error[2], $error[1]);
}
unset($bindResult);// ไม่ใช้ก็ unset คืนพื้นที่ให้หน่วยความจำ
$executeResult = $sth->execute();
if (false === $executeResult) {
// ถ้าการ execute ไม่สำเร็จจะได้ค่าเป็น false
// อ้างอิง https://www.php.net/manual/en/pdostatement.execute.php
$error = $sth->errorInfo();
throw new \Exception('SQL state[' . $error[0] . ']: ' . $error[2], $error[1]);
}
unset($executeResult);// ไม่ใช้ก็ unset คืนพื้นที่ให้หน่วยความจำ
$rows = $sth->fetchAll(\PDO::FETCH_OBJ);
if (false === $rows) {
// ถ้าการ execute ไม่สำเร็จจะได้ค่าเป็น false
// อ้างอิง https://www.php.net/manual/en/pdostatement.fetchall.php
$error = $sth->errorInfo();
throw new \Exception('SQL state[' . $error[0] . ']: ' . $error[2], $error[1]);
}
} catch (\Exception $ex) {
// ถ้ากำหนดใน option ใน config ให้ throw exception เมื่อขั้นตอนใดไม่สำเร็จอาจมีการ throw exception ได้.
// ขั้นตอนตรงนี้มีไว้เพื่อดัก exception แล้วเขียน error ใหม่ให้ดูง่ายตามต้องการ.
echo 'Exception catched: ' . $ex->getMessage() . ' [Code: ' . $ex->getCode() . ']<br>' . PHP_EOL;
echo $ex->getFile() . ' on line ' . $ex->getLine() . '<br>' . PHP_EOL;
}// end try..catch;
if (isset($rows) && is_array($rows)) {
foreach ($rows as $row) {
echo '<tr>' . PHP_EOL;
echo '<td>' . $row->id . '</td>' . PHP_EOL;
echo '<td>' . $row->name . '</td>' . PHP_EOL;
echo '<td>' . $row->address . '</td>' . PHP_EOL;
echo '<td>' . date('Y-m-d H:i:s', (int) $row->date) . '</td>' . PHP_EOL;
echo '</tr>' . PHP_EOL;
}// endforeach;
unset($row);
}
unset($rows);
?>
</tbody>
</table>
<?php
if (isset($sth) && $sth instanceof \PDOStatement) {
// ถ้าการเชื่อมต่อสำเร็จ ตัวแปร $sth จะผ่านมาถึงที่นี่โดยไม่ติด error.
// debug ดูว่า bindValue อะไรบ้าง?
echo '<pre>';
$sth->debugDumpParams();
echo '</pre>' . PHP_EOL;
// ควรใช้ $sth->closeCursor() เพื่อคืนพื้นที่ให้หน่วยความจำ
$sth->closeCursor();
unset($sth);
}
?>
</body>
</html>
<?php
// ปิดการเชื่อมต่อ
$PDO = null;
sample-pdo-functions.php
หวังว่าจะเป็นประโยชน์บ้างนะครับ
Tag : PHP, MySQL, MySQL
|
|
|
|
|
|
Date :
2021-08-07 15:23:43 |
By :
mr.v |
View :
710 |
Reply :
4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
excellent practice +1
|
|
|
|
|
Date :
2021-08-07 15:29:18 |
By :
TheGreatGod_of_Death |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
เพิ่มเติม การอ้างอิงคลาสจาก global space ไม่จำเป็นต้องใช้ \ นำหน้า เช่น
Code (PHP)
if (isset($sth) && $sth instanceof \PDOStatement
สามารถใช้
Code (PHP)
if (isset($sth) && $sth instanceof PDOStatement
เป็นต้น
อย่าพึ่งเชื่อ...จะใช่หรือไม่ลองพิสูจน์ ผมดูแค่ผ่านๆ ไม่ได้อ้างอิง อาจฟาวล์
|
|
|
|
|
Date :
2021-08-07 15:33:04 |
By :
TheGreatGod_of_Death |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ขอบคุณครับ
|
|
|
|
|
Date :
2021-08-16 08:53:19 |
By :
kittitnun |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Load balance : Server 02
|