本文以通訊錄系統為例,演示 MySQL 建庫建表、PHP 連接、查詢渲染全流程,並對比 mysqli 與 PDO 兩種現代寫法,確立安全、可維護的數據庫交互規範。
CREATE DATABASE `txl` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE `txl`;
CREATE TABLE `personal_info` (
`pi_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`pi_name` VARCHAR(50) NOT NULL,
`pi_tel` VARCHAR(20) DEFAULT NULL,
`pi_qq` VARCHAR(20) DEFAULT NULL,
`pi_email` VARCHAR(100) DEFAULT NULL,
PRIMARY KEY (`pi_id`),
KEY `idx_name` (`pi_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `personal_info` (`pi_name`, `pi_tel`, `pi_qq`, `pi_email`) VALUES
('張三', '13911111111', '642864125', 'zhangsan@126.com'),
('李四', '13122222222', '63958741', 'lisi@163.com'),
('王五', '13833333333', '912345678', 'wangwu@sohu.com');
<?php
// config/db.php
return [
'dsn' => 'mysql:host=127.0.0.1;dbname=txl;charset=utf8mb4',
'user' => 'root',
'pass' => 'root',
'options' => [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false, // 真實預處理
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4",
],
];
// index.php
require 'config/db.php';
$config = require 'config/db.php';
try {
$pdo = new PDO($config['dsn'], $config['user'], $config['pass'], $config['options']);
} catch (PDOException $e) {
die('DB Connection failed: ' . $e->getMessage());
}
$stmt = $pdo->query('SELECT * FROM personal_info');
$rows = $stmt->fetchAll();
// 輸出 HTML 表格
echo '<table border="1" cellpadding="5" cellspacing="0">';
echo '<tr><th>ID</th><th>姓名</th><th>電話</th><th>QQ</th><th>郵箱</th></tr>';
foreach ($rows as $row) {
echo '<tr>';
foreach ($row as $val) {
echo '<td>' . htmlspecialchars($val, ENT_QUOTES, 'UTF-8') . '</td>';
}
echo '</tr>';
}
echo '</table>';
$mysqli = new mysqli('127.0.0.1', 'root', 'root', 'txl');
if ($mysqli->connect_errno) die('Connect failed: ' . $mysqli->connect_error);
$mysqli->set_charset('utf8mb4');
$result = $mysqli->query('SELECT * FROM personal_info');
if ($result) {
echo '<table border="1"><tr><th>ID</th><th>姓名</th><th>電話</th><th>QQ</th><th>郵箱</th></tr>';
while ($row = $result->fetch_assoc()) {
echo '<tr>';
foreach ($row as $val) echo '<td>' . htmlspecialchars($val) . '</td>';
echo '</tr>';
}
echo '</table>';
$result->free();
}
$mysqli->close();
prepare/bind_param/execute),拒絕字符串拼接。ERRMODE_EXCEPTION,mysqli 執行 mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT)。config/db.php,.gitignore 排除,生產環境用環境變量注入。htmlspecialchars(),防 XSS。$stmt->closeCursor() / $result->free(),長運行腳本尤為重要。class ContactRepository {
private PDO $pdo;
public function __construct(PDO $pdo) { $this->pdo = $pdo; }
public function findAll(): array {
return $this->pdo->query('SELECT * FROM personal_info')->fetchAll();
}
public function findByName(string $name): ?array {
$stmt = $this->pdo->prepare('SELECT * FROM personal_info WHERE pi_name = ?');
$stmt->execute([$name]);
return $stmt->fetch() ?: null;
}
public function create(array $data): int {
$stmt = $this->pdo->prepare('INSERT INTO personal_info (pi_name,pi_tel,pi_qq,pi_email) VALUES (?,?,?,?)');
$stmt->execute([$data['name'], $data['tel'], $data['qq'], $data['email']]);
return (int)$this->pdo->lastInsertId();
}
}
從「能跑通」到「寫得對、改得快、抗得住」,建立規範的數據庫訪問層是每個 PHP 專案成長的必經之路。