首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 連接 MySQL 讀取數據完整範例 (含亂碼解決、PDO 最佳實踐)

     編輯:PHP 相關知識

PHP 操作 MySQL 經歷過 `mysql_*` (已移除)、`mysqli`、`PDO` 三個時代。現代項目**強制推薦 PDO**:支援預處理防注入、多數據庫抽象、異常處理、事務管理。本文提供從連接、查詢、顯示、編碼處理到錯誤處理的完整最佳實踐範例。

現代標準:PDO 連接與查詢

<?php
// config.php - 單例獲取 PDO 實例
function getPdo(): PDO {
    static $pdo = null;
    if ($pdo instanceof PDO) return $pdo;

    $host = '127.0.0.1';
    $db   = 'infosystem';
    $user = 'root';
    $pass = 'your_secure_password';
    $charset = 'utf8mb4'; // 支援 Emoji

    $dsn = "mysql:host=$host;dbname=$db;charset=$charset";
    $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 $charset COLLATE utf8mb4_unicode_ci",
    ];

    try {
        $pdo = new PDO($dsn, $user, $pass, $options);
    } catch (PDOException $e) {
        // 生產環境記錄日誌,不輸出細節
        error_log("DB Connection Failed: " . $e->getMessage());
        die('資料庫連接失敗,請稍後再試');
    }
    return $pdo;
}

// index.php - 讀取並顯示
require 'config.php';
$pdo = getPdo();

try {
    $stmt = $pdo->query("SELECT dept_name, emp_name, pc_name FROM info ORDER BY id DESC LIMIT 50");
    $rows = $stmt->fetchAll();
} catch (PDOException $e) {
    error_log("Query Failed: " . $e->getMessage());
    die('數據查詢失敗');
}
?>



    
    員工信息列表
    


    

部門員工信息

部門名稱員工姓名PC 名稱

預處理防注入 (帶參數查詢)

<?php
$dept = $_GET['dept'] ?? '';
$stmt = $pdo->prepare("SELECT * FROM info WHERE dept_name = ? LIMIT 20");
$stmt->execute([$dept]);
$rows = $stmt->fetchAll();
// ? 佔位符自動轉義,杜絕 SQL 注入
?>

事務處理 (轉帳、批量寫入)

<?php
try {
    $pdo->beginTransaction();
    $pdo->exec("UPDATE accounts SET balance = balance - 100 WHERE user = 'A'");
    $pdo->exec("UPDATE accounts SET balance = balance + 100 WHERE user = 'B'");
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
    error_log("Transaction Failed: " . $e->getMessage());
}

中文亂碼徹底解決 (三步走)

  1. 資料庫/表/欄位:`CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`
  2. 連接層:DSN 帶 `charset=utf8mb4` + `SET NAMES utf8mb4` (PDO `MYSQL_ATTR_INIT_COMMAND`)
  3. 輸出層:`header("Content-Type: text/html; charset=UTF-8")` + HTML `` + 文件保存為 **UTF-8 無 BOM**

舊項目遷移提醒:若歷史數據為 `latin1` 存儲實際 UTF-8 內容 (雙重編碼),需先 `ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4`,或導出 SQL 文件手動修正後導入。

舊版 mysqli 寫法 (僅供維護參考)

<?php
$mysqli = new mysqli('localhost', 'root', 'pwd', 'infosystem');
if ($mysqli->connect_errno) die('連接失敗: ' . $mysqli->connect_error);
$mysqli->set_charset('utf8mb4');

$sql = "SELECT dept_name, emp_name, pc_name FROM info";
$res = $mysqli->query($sql);
if (!$res) die('查詢失敗: ' . $mysqli->error);

echo "";
while ($row = $res->fetch_assoc()) {
    echo "";
}
echo "
部門員工PC
{$row['dept_name']}{$row['emp_name']}{$row['pc_name']}
"; $res->free(); $mysqli->close(); ?>

極簡 mysqli 過渡版 (解決原文中的 GB2312 亂碼)

<?php
$link = mysqli_connect("localhost", "root", "password", "infosystem");
if (!$link) die("連接失敗!");
mysqli_set_charset($link, "utf8mb4"); // 關鍵:替換原文的 SET NAMES GB2312

$q = "SELECT * FROM info";
$rs = mysqli_query($link, $q);
if (!$rs) die("查詢失效!");

echo "";
while ($row = mysqli_fetch_array($rs)) {
    echo "";
}
echo "
部門名稱員工姓名PC名稱
{$row[1]}{$row[2]}{$row[3]}
"; mysqli_free_result($rs); mysqli_close($link); ?>

常見錯誤對照表

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
現象原因修正
顯示連接層未 SET NAMES / charset 不匹配DSN 加 charset、mysqli_set_charset、SET NAMES
???? 顯示資料庫欄位 charset 非 utf8mb4ALTER TABLE ... CONVERT TO CHARSET utf8mb4
Emoji 變 ?使用 utf8 (utf8mb3)全鏈路升級 utf8mb4
SQL 注入成功字串拼接 SQL強制預處理 prepare/execute
Cannot modify header輸出前有空白/BOM/echo檢查入口文件、關閉 output_buffering