<?php
function loadFilterWords($file = 'filterwords.txt'): array {
if (!is_file($file) || !is_readable($file)) return [];
$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
return array_map('trim', $lines);
}
<?php
function checkSensitiveWords(string $content, array $words): bool {
foreach ($words as $w) {
if ($w === '') continue;
// 使用 preg_quote 避免特殊字元干擾,i 忽略大小寫
if (preg_match('/' . preg_quote($w, '/') . '/iu', $content)) {
return false; // 含敏感詞
}
}
return true; // 通過
}
// 使用範例
$filterWords = loadFilterWords();
$content = $_POST['content'] ?? '';
if (!checkSensitiveWords($content, $filterWords)) {
exit('');
}
// 繼續存儲...
?>
<?php
function addFilterWord(string $word, string $file = 'filterwords.txt'): bool {
$word = trim($word);
if ($word === '') return false;
if (!is_writable($file)) return false;
$fp = fopen($file, 'a'); // 追加模式
if (!$fp) return false;
flock($fp, LOCK_EX);
fwrite($fp, $word . "\n");
flock($fp, LOCK_UN);
fclose($fp);
return true;
}
<?php
$words = loadFilterWords();
echo '敏感詞:' . implode('、', $words);
| 函數 | 用途 | 關鍵參數 |
|---|---|---|
| is_writable() | 判斷可寫 | 路徑 |
| fopen() | 開啟檔案 | 模式: r/w/a/r+/w+/a+ |
| fseek() | 移動指標 | SEEK_SET/SEEK_CUR/SEEK_END |
| fgets() | 逐行讀取 | 長度限制 |
| fwrite() | 寫入字串 | 長度限制 (可選) |
| fclose() | 關閉指標 | - |
| file() | 整檔讀陣列 | FLAGS |
| file_get_contents() | 整檔讀字串 | - |
| unlink() | 刪除檔案 | - |
substr() 按位元組截取,中文 (UTF-8 3 位元組) 易斷碼產生 。解法:使用 mb_substr() 或 iconv_substr()。
<?php
function mbCut(string $str, int $start, int $length, string $encoding = 'UTF-8'): string {
$cut = mb_substr($str, $start, $length, $encoding);
// 可選:超過長度加省略號
if (mb_strlen($str, $encoding) > $start + $length) {
$cut .= '...';
}
return $cut;
}
// 範例
$str = '這是一段測試中文字串';
echo mbCut($str, 0, 10); // 這是一段測試中文...
?>
<?php
// 防 XSS:輸出前轉義
$safe = htmlspecialchars($userInput, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
// 字串替換 (不支援正則)
$new = str_replace('舊詞', '新詞', $content);
// 多組替換
$new = str_replace(['A', 'B'], ['C', 'D'], $content);
// 計算替換次數
$count = 0;
$new = str_replace('搜尋', '替換', $content, $count);
<table id="msgList">
<thead>
<tr><th><input type="checkbox" id="selectAll"> 全選</th><th>內容</th></tr>
</thead>
<tbody>
<?php foreach ($messages as $m): ?>
<tr>
<td><input type="checkbox" name="msg_ids[]" value="<?= $m['id'] ?>"></td>
<td><?= htmlspecialchars($m['content']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<script>
const selectAll = document.getElementById('selectAll');
const checkboxes = document.querySelectorAll('input[name="msg_ids[]"]');
selectAll.addEventListener('change', () => {
checkboxes.forEach(cb => cb.checked = selectAll.checked);
});
// 反選按鈕
document.getElementById('inverseBtn').addEventListener('click', () => {
checkboxes.forEach(cb => cb.checked = !cb.checked);
selectAll.checked = [...checkboxes].every(cb => cb.checked);
});
// 取得已選 ID
function getSelectedIds() {
return [...checkboxes].filter(cb => cb.checked).map(cb => cb.value);
}
</script>
文字檔並發效能差、難查詢、易損壞。建議遷移至 MySQL/SQLite:
CREATE TABLE messages (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
nickname VARCHAR(50) NOT NULL,
content TEXT NOT NULL,
ip VARCHAR(45),
user_agent VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_approved TINYINT(1) DEFAULT 1,
INDEX idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
配合 PDO + Prepared Statements,徹底解決並發與安全問題。