表單中的 <textarea> 使用者輸入的純文字,若直接輸出到網頁會失去換行與空白格式。本文介紹三種將純文字轉為 HTML 的方案,從簡易函式到現代標準庫,滿足不同專案需求。
針對簡單需求,可自行封裝轉換函式:
/**
* 純文字轉 HTML:保留換行、段落結構
* @param string $text 原始文字
* @return string HTML 字串
*/
function textToHtml($text)
{
// 1. 移除首尾空白
$text = trim($text);
// 2. 統一換行符為 \n
$text = str_replace(["\r\n", "\r"], "\n", $text);
// 3. 連續空行合併為單一段落分隔
$text = preg_replace("/\n{3,}/", "\n\n", $text);
// 4. 雙換行 → 段落標籤
$paragraphs = explode("\n\n", $text);
$html = '';
foreach ($paragraphs as $para) {
$para = trim($para);
if ($para === '') continue;
// 單換行 →
$para = nl2br($para);
$html .= "<p>{$para}</p>\n";
}
return $html;
}
// 使用範例
$input = "第一行\n第二行\n\n第三段第一行\n第三段第二行";
echo textToHtml($input);
輸出結果:
<p>第一行<br> 第二行</p> <p>第三段第一行<br> 第三段第二行</p>
PHP 內建 nl2br() 將換行轉為 <br>,搭配段落包裝:
function simpleTextToHtml($text)
{
$text = trim($text);
$text = nl2br($text);
// 將連續
視為段落分隔
$text = preg_replace('#(?:<br>\s*){2,}#', '</p><p>', $text);
return '<p>' . $text . '</p>';
}
注意:此法較粗糙,複雜結構易產生無效 HTML。
專案若已使用 Composer,強烈建議引入專業庫:
composer require league/commonmark
use League\CommonMark\CommonMarkConverter; $converter = new CommonMarkConverter(); $html = $converter->convertToHtml($markdownText);
支援完整 Markdown 語法,輸出安全、標準的 HTML。
composer require ezyang/htmlpurifier
use HTMLPurifier;
use HTMLPurifier_Config;
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.Doctype', 'HTML 4.01 Transitional');
$config->set('AutoFormat.RemoveEmpty', true);
$config->set('AutoFormat.AutoParagraph', true); // 自動加
$purifier = new HTMLPurifier($config);
$cleanHtml = $purifier->purify($userInput);
同時解決「純文字轉 HTML」與「XSS 防護」兩大需求,企業級專案首選。
無論採用哪種方案,**輸出到瀏覽器前務必經過跳脫處理**,除非你完全信任來源且已經過淨化:
// 僅在確定 $html 已經過 HTMLPurifier 淨化時才直接輸出 echo $html; // 一般情況:輸出純文字內容時 echo htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
| 方案 | 適用場景 | 優點 | 缺點 |
|---|---|---|---|
| 自訂函式 | 輕量專案、無 Composer | 零依賴、可控性高 | 需自行處理邊界情況 |
| nl2br() 包裝 | 快速原型、簡單需求 | 程式碼極少 | HTML 結構不嚴謹 |
| CommonMark | 支援 Markdown 輸入 | 標準化、擴充性強 | 學習曲線稍高 |
| HTMLPurifier | 生產環境、UGC 內容 | 安全性最高、輸出合規 | 效能較低、體積較大 |
建議:新專案直接採用 HTMLPurifier,舊專案若無法引入套件,使用方案一的自訂函式並搭配 htmlspecialchars() 輸出。