PHP 程式連線
PHP 連線 MySQL 通常使用 **PDO** 或 **MySQLi**。建議使用 PDO,因為介面一致、支援例外處理,也方便使用預備語句防止 SQL Injection。
## 一、使用 PDO 連線 MySQL
```php
<?php
$host = 'localhost';
$dbname = 'test_db';
$user = 'root';
$password = 'your_password';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$dbname;charset=$charset";
try {
$pdo = new PDO($dsn, $user, $password);
// 發生錯誤時使用例外處理
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 查詢結果以關聯陣列形式取得
$pdo->setAttribute(
PDO::ATTR_DEFAULT_FETCH_MODE,
PDO::FETCH_ASSOC
);
echo "資料庫連線成功";
} catch (PDOException $e) {
die("資料庫連線失敗:" . $e->getMessage());
}
?>
```
其中:
- `host`:資料庫主機,例如 `localhost`
- `dbname`:資料庫名稱
- `user`:MySQL 帳號
- `password`:MySQL 密碼
- `charset=utf8mb4`:支援中文及 Emoji 等文字
---
## 二、執行不回傳資料的 SQL 指令
例如建立資料表、更新資料或刪除資料,可以使用 `exec()`。
```php
$sql = "
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(200) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
";
$pdo->exec($sql);
```
### 新增資料
雖然可以直接組合 SQL 字串,但不建議這樣做:
```php
// 不建議,可能產生 SQL Injection
$sql = "INSERT INTO users (name, email)
VALUES ('$name', '$email')";
```
應使用 **預備語句**:
```php
$name = '王小明';
$email = 'ming@example.com';
$sql = "INSERT INTO users (name, email)
VALUES (:name, :email)";
$stmt = $pdo->prepare($sql);
$stmt->execute([
':name' => $name,
':email' => $email
]);
echo "新增成功,編號:" . $pdo->lastInsertId();
```
也可以使用問號作為參數:
```php
$sql = "INSERT INTO users (name, email) VALUES (?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$name, $email]);
```
---
## 三、執行查詢並取得資料
### 1. 查詢全部資料
```php
$sql = "SELECT id, name, email FROM users ORDER BY id DESC";
$stmt = $pdo->query($sql);
$users = $stmt->fetchAll();
foreach ($users as $user) {
echo "編號:" . htmlspecialchars($user['id']) . "<br>";
echo "姓名:" . htmlspecialchars($user['name']) . "<br>";
echo "Email:" . htmlspecialchars($user['email']) . "<hr>";
}
```
`fetchAll()` 會一次取得所有資料。
---
### 2. 一筆一筆取得資料
當資料很多時,可以使用 `fetch()` 逐筆讀取:
```php
$sql = "SELECT id, name, email FROM users";
$stmt = $pdo->query($sql);
while ($user = $stmt->fetch()) {
echo $user['id'] . ' - ';
echo htmlspecialchars($user['name']) . ' - ';
echo htmlspecialchars($user['email']) . '<br>';
}
```
---
### 3. 使用條件查詢
例如根據使用者編號查詢:
```php
$id = 1;
$sql = "SELECT id, name, email
FROM users
WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute([':id' => $id]);
$user = $stmt->fetch();
if ($user) {
echo "姓名:" . htmlspecialchars($user['name']);
echo "<br>Email:" . htmlspecialchars($user['email']);
} else {
echo "找不到資料";
}
```
---
## 四、更新資料
```php
$id = 1;
$name = '李小華';
$email = 'hua@example.com';
$sql = "
UPDATE users
SET name = :name, email = :email
WHERE id = :id
";
$stmt = $pdo->prepare($sql);
$stmt->execute([
':name' => $name,
':email' => $email,
':id' => $id
]);
echo "更新筆數:" . $stmt->rowCount();
```
---
## 五、刪除資料
```php
$id = 1;
$sql = "DELETE FROM users WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute([':id' => $id]);
echo "刪除筆數:" . $stmt->rowCount();
```
---
## 六、使用交易 Transaction
當多個 SQL 必須全部成功,或全部失敗時,可以使用交易:
```php
try {
$pdo->beginTransaction();
$stmt = $pdo->prepare(
"INSERT INTO users (name, email)
VALUES (:name, :email)"
);
$stmt->execute([
':name' => '甲',
':email' => 'a@example.com'
]);
$stmt->execute([
':name' => '乙',
':email' => 'b@example.com'
]);
$pdo->commit();
echo "全部新增成功";
} catch (Exception $e) {
$pdo->rollBack();
echo "操作失敗,已取消所有變更";
}
```
---
## 七、使用 MySQLi 的簡單範例
除了 PDO,也可以使用 MySQLi:
```php
<?php
$conn = new mysqli(
'localhost',
'root',
'your_password',
'test_db'
);
if ($conn->connect_error) {
die("連線失敗:" . $conn->connect_error);
}
$conn->set_charset('utf8mb4');
$sql = "SELECT id, name, email FROM users";
$result = $conn->query($sql);
while ($row = $result->fetch_assoc()) {
echo $row['id'] . ' - ';
echo htmlspecialchars($row['name']) . ' - ';
echo htmlspecialchars($row['email']) . '<br>';
}
$conn->close();
?>
```
使用 MySQLi 預備語句:
```php
$stmt = $conn->prepare(
"SELECT id, name, email FROM users WHERE id = ?"
);
$id = 1;
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['name'];
}
```
`bind_param()` 中的型別:
- `i`:整數
- `d`:浮點數
- `s`:字串
- `b`:二進位資料
---
## 八、實務注意事項
1. **輸入值不要直接串接到 SQL**
```php
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute(['email' => $email]);
```
2. **顯示網頁內容時使用 `htmlspecialchars()`**
```php
echo htmlspecialchars($user['name'], ENT_QUOTES, 'UTF-8');
```
3. **資料庫密碼不要直接放在公開版本控制中**,可使用環境變數或設定檔。
4. **使用 `utf8mb4`**,避免中文或特殊符號亂碼。
5. `query()` 適合執行沒有外部輸入的固定 SQL;只要 SQL 包含使用者輸入,就應使用 `prepare()` 和 `execute()`。
基本流程就是:
```text
建立連線
↓
準備或執行 SQL
↓
傳入參數
↓
取得結果
↓
逐筆或全部讀取資料
↓
關閉連線
```
實務上最推薦的方式是:**PDO + prepared statement + 例外處理**。
相關學習地圖、教學課程
Python 後端工程、資料庫