早期 PHP 開發中,透過 URL 查詢字串 (?id=123) 傳遞文章識別碼至評論頁面是最直觀的參數傳遞方式。本文展示基本實作與現代改良建議。
<?php
// 假設從資料庫讀取文章列表
$articles = [
['id' => 1, 'title' => 'PHP 入門教學'],
['id' => 2, 'title' => 'MySQL 基礎操作'],
['id' => 3, 'title' => 'Apache 配置技巧'],
];
?>
<html>
<body>
<h1>文章列表</h1>
<ul>
<?php foreach ($articles as $art): ?>
<li>
<a href="article.php?id=<?= $art['id'] ?>">
<?= htmlspecialchars($art['title']) ?>
</a>
|
<a href="comments.php?id=<?= $art['id'] ?>">
查看評論
</a>
</li>
<?php endforeach; ?>
</ul>
</body>
</html>
<?php
$id = $_GET['id'] ?? 0;
// 實際專案應使用 Prepared Statements 防 SQL 注入
$stmt = $pdo->prepare("SELECT * FROM articles WHERE id = ?");
$stmt->execute([$id]);
$article = $stmt->fetch();
if (!$article) {
http_response_code(404);
die("文章不存在");
}
?>
<html>
<body>
<h1><?= htmlspecialchars($article['title']) ?></h1>
<div><?= nl2br(htmlspecialchars($article['content'])) ?></div>
<p><a href="comments.php?id=<?= $id ?>">前往評論區</a></p>
</body>
</html>
<?php
$id = $_GET['id'] ?? 0;
$stmt = $pdo->prepare("SELECT * FROM comments WHERE article_id = ? ORDER BY created_at DESC");
$stmt->execute([$id]);
$comments = $stmt->fetchAll();
// 同時取得文章標題供顯示
$stmt = $pdo->prepare("SELECT title FROM articles WHERE id = ?");
$stmt->execute([$id]);
$article = $stmt->fetch();
?>
<html>
<body>
<h1><?= htmlspecialchars($article['title']) ?> - 讀者評論</h1>
<ul>
<?php foreach ($comments as $c): ?>
<li>
<strong><?= htmlspecialchars($c['author']) ?></strong>:
<?= htmlspecialchars($c['content']) ?>
<small><?= $c['created_at'] ?></small>
</li>
<?php endforeach; ?>
</ul>
</body>
</html>
| 方式 | 範例 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|---|
| GET 查詢字串 | page.php?id=123 | 可書籤、可分享、SEO 友善、瀏覽器歷史記錄 | 長度限制、參數暴露、不適合敏感資料 | 文章閱讀、搜尋、分頁、公開資源 |
| POST 表單 | form action="page.php" method="POST" | 無長度限制、參數不在 URL、適合敏感操作 | 不可書籤、重新整理會重複提交 | 登入、發表評論、修改資料、上傳檔案 |
| Session | $_SESSION['article_id'] = 123 | 跨頁面持久、伺服器端儲存 | 依賴 Cookie、多標籤頁狀態同步問題 | 多步驟精靈、購物車、用戶登入狀態 |
| URL 路徑參數 (REST) | /article/123/comments | 語意清晰、SEO 最佳、API 標準 | 需 Web Server Rewrite 規則支援 | 現代框架 (Laravel/Symfony)、REST API |
- SQL 注入:絕對禁止 直接拼接
"SELECT * FROM t WHERE id=$id"。必須使用 Prepared Statements (PDO/mysqli)- XSS 攻擊:所有輸出 HTML 內容必須
htmlspecialchars()轉義- ID 遍歷洩露:若需隱藏資料量,使用 UUID、Hashids 或 Slug 替代自增 ID
- 授權檢查:評論刪除/編輯必須驗證當前用戶擁有權限,而非僅靠 ID
// routes/web.php
Route::get('/article/{id}', 'ArticleController@show')->name('article.show');
Route::get('/article/{id}/comments', 'CommentController@index')->name('article.comments');
// Controller
public function show($id) {
$article = Article::findOrFail($id); // 自動 404
return view('article.show', compact('article'));
}
// Blade 模板產生連結
<a href="{{ route('article.comments', $article->id) }}">查看評論</a>