處理使用者輸入的網址時,常需自動補上 https:// 或 https://,並將純文字網址/Email 轉為可點擊超連結。本文提供兩個實用函式,並說明正則表達式邏輯與邊界情況處理。
<?php
/**
* 確保網址包含 scheme (http/https/ftp),否則預設補上 https://
*
* @param string $url 使用者輸入的網址
* @return string 補全 scheme 後的網址
*/
function ensureScheme(string $url): string {
$url = trim($url);
if ($url === '') {
return '';
}
// 已有 scheme 直接回傳
if (preg_match('~^https?://|^ftp://~i', $url)) {
return $url;
}
// 無 scheme,預設 https
return 'https://' . $url;
}
// 測試
var_dump(ensureScheme('example.com')); // https://example.com
var_dump(ensureScheme('https://example.com')); // https://example.com
var_dump(ensureScheme('ftp://files.com')); // ftp://files.com
<?php
/**
* 將字串中的 URL、Email 轉為 <a> 標籤
*
* @param string $text 原始文字
* @param array $options 選項 ['target' => '_blank', 'rel' => 'noopener noreferrer', 'class' => 'auto-link']
* @return string 轉換後的 HTML
*/
function autoLink(string $text, array $options = []): string {
$defaultOptions = [
'target' => '_blank',
'rel' => 'noopener noreferrer',
'class' => 'auto-link',
];
$opts = array_merge($defaultOptions, $options);
$attr = sprintf('target="%s" rel="%s" class="%s"',
htmlspecialchars($opts['target']),
htmlspecialchars($opts['rel']),
htmlspecialchars($opts['class'])
);
// 1. 處理已有 scheme 的 URL (http/https/ftp)
// 避免重複處理已經是連結的情況 (簡易判斷:前後無 "\']+~i',
function ($m) use ($attr) {
$url = htmlspecialchars($m[0]);
return "<a href=\"{$url}\" {$attr}>{$url}</a>";
},
$text
);
// 2. 處理無 scheme 的 www. 開頭網址
$text = preg_replace_callback(
'~(?"\']+~i',
function ($m) use ($attr) {
$url = 'https://' . $m[0];
$display = htmlspecialchars($m[0]);
return "<a href=\"" . htmlspecialchars($url) . "\" {$attr}>{$display}</a>";
},
$text
);
// 3. 處理 Email
$text = preg_replace_callback(
'~(?
| 模式 | 說明 |
|---|---|
(? | 負向後顧斷言:確保前方非 href=" 或 href=',避免二次包裝已經是連結的文字 |
\b(https?|ftp):// | 單字邊界 + scheme,支援 http、https、ftp |
[^\s<>"\']+ | 非空白、非標籤字元、非引號,匹配 URL 主體 |
\bwww\.[^\s<>"\']+ | 匹配 www. 開頭無 scheme 網址 |
[\w.+-]+@[\w-]+\.[\w.-]+ | 簡易 Email 模式 (RFC 5322 完整版極複雜,實務上此版本足夠) |
若輸入內容不可信,建議先用 HTML Purifier 清理,再套用 autoLink():
require_once 'HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);
$cleanHtml = $purifier->purify($userInput);
$finalHtml = autoLink($cleanHtml);
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$rawUrl = $_POST['url'] ?? '';
$url = ensureScheme($rawUrl);
$comment = $_POST['comment'] ?? '';
$commentHtml = autoLink($comment);
// 儲存 $url, $commentHtml 到資料庫...
// 顯示時直接輸出 $commentHtml (已含連結)
}
ensureScheme():輕量級補全協定,預設 https:// 更安全。autoLink():使用 preg_replace_callback 精確控制替換邏輯,避免巢狀連結、XSS 風險。