系統需求
- 新聞以純文字檔 (
.txt) 儲存在 /announce/ 目錄
- 首頁自動掃描目錄,依檔案**最後存取時間** (
fileatime) 由新到舊排序顯示
- 每則新聞顯示:日期時間 + 完整內容(逐行輸出)
核心程式碼 index.php
<?php
include 'makestr.php'; // 假設含共用函數
include 'head.php'; // 頁首 HTML
$newspath = '/announce/';
$newsFiles = [];
$hd = dir($newspath);
while (($file = $hd->read()) !== false) {
if (strtolower(pathinfo($file, PATHINFO_EXTENSION)) !== 'txt') continue;
$fullPath = $newspath . $file;
// 取最後存取時間 (atime);建議改用 filemtime (修改時間) 較直覺
$lastAccess = fileatime($fullPath);
$newsFiles[$file] = $lastAccess;
}
$hd->close();
// 依時間由大到小排序 (最新在前)
arsort($newsFiles);
// 輸出新聞
foreach ($newsFiles as $file => $timestamp) {
$lines = file($newspath . $file, FILE_IGNORE_NEW_LINES);
echo '<p>' . date('d.m.Y-H:i:s', $timestamp) . '<br>' . "\n";
foreach ($lines as $line) {
$line = rtrim($line); // 移除尾部空白/換行
$line = htmlspecialchars($line); // 防 XSS
echo $line . '</p>' . "\n";
}
}
include 'tail.php'; // 頁尾 HTML
?>
關鍵函數說明
| 函數 | 用途 | 注意事項 |
dir() | 返回目錄控制代碼,支援 read()/close() | PHP 4 風格,現代可用 scandir() + foreach |
fileatime() | 取得檔案最後存取時間 (Unix timestamp) | 頻繁讀取會更新 atime 導致排序抖動;生產建議用 filemtime() (內容修改時間) 或 filectime() (inode 變更時間) |
arsort() | 關聯陣列依值由大到小排序,保留鍵值關聯 | 鍵值為檔名,值為 timestamp |
file() | 將檔案讀入陣列,每行一個元素 | 大檔案會佔記憶體;新聞純文字通常較小可接受 |
htmlspecialchars() | 將特殊字元轉為 HTML 實體 | 必要防 XSS,旗標 ENT_QUOTES | ENT_SUBSTITUTE 更完整 |
現代化重寫(PHP 8 + 物件導向)
<?php
// NewsRepository.php
class NewsRepository {
private string $dir;
public function __construct(string $dir) { $this->dir = rtrim($dir, '/') . '/'; }
public function getAllSortedByMtimeDesc(): array {
$files = glob($this->dir . '*.txt');
usort($files, fn($a, $b) => filemtime($b) <=> filemtime($a));
return array_map(fn($f) => [
'filename' => basename($f),
'mtime' => filemtime($f),
'content' => array_map('htmlspecialchars', file($f, FILE_IGNORE_NEW_LINES)),
], $files);
}
}
// index.php
require 'NewsRepository.php';
$repo = new NewsRepository(__DIR__ . '/announce');
$newsList = $repo->getAllSortedByMtimeDesc();
?>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>最新消息</title></head><body>
<?php foreach ($newsList as $news): ?>
<article>
<header><time datetime="<?= date('c', $news['mtime']) ?>"><?= date('Y-m-d H:i', $news['mtime']) ?></time></header>
<div><?= implode('<br>', $news['content']) ?></div>
</article>
<?php endforeach; ?>
</body></html>
下一階段預告(對應第 4 講)
- 自動刪除超過 N 天的舊新聞 (
filemtime + unlink)
- 後台上傳 .txt 檔 (multipart/form-data)
- 線上編輯現有新聞 (避免上傳執行檔風險)