在 CMS、部落格、電商商品列表等場景中,常需顯示文章/商品的「第一張圖片」作為縮圖。當內容無圖片時,需提供預設佔位圖。本文提供兩種實作:隨機預設圖與固定預設圖,並說明正則優化要點。
<?php
/**
* 從 HTML 內容提取第一張圖片 URL
* @param string $content 文章內容
* @param string $defaultDir 預設圖目錄
* @param bool $random 是否隨機選取預設圖
* @return string 圖片 URL
*/
function get_first_image($content, $defaultDir = 'images/random/', $random = true) {
// 改良正則:支援單雙引號、屬性順序不固定、跨行
$pattern = '/<img[^>]+src=[\'"]([^\'"]+\.(?:gif|jpg|jpeg|png|webp))[\'"][^>]*>/i';
if (preg_match($pattern, $content, $matches)) {
return $matches[1]; // 找到第一張圖
}
// 無圖片時的回退邏輯
if ($random) {
$num = mt_rand(1, 4); // 1~4.jpg
return $defaultDir . $num . '.jpg';
} else {
return './images/no-image.jpg'; // 固定預設圖
}
}
// 使用範例
$articleContent = $article->Content; // 假設來自資料庫
$thumb = get_first_image($articleContent);
echo '<img src="' . $thumb . '" alt="文章縮圖">';
?>
/<img[^>]+src=[\'"]([^\'"]+\.(?:gif|jpg|jpeg|png|webp))[\'"][^>]*>/i
<img:匹配標籤開頭(不區分大小寫)[^>]+:匹配任意非 > 字元(涵蓋 class、id、data-* 等屬性)src=[\'"]:匹配 src 屬性,支援單引號或雙引號([^\'"]+\.(?:gif|jpg|jpeg|png|webp)):捕獲群組,取得副檔名為圖片格式的 URL[\'"][^>]*>:匹配結尾引號至標籤結束i 修飾符:大小寫不敏感(匹配 <IMG>、<Img>)改進點:原文正則使用 .*? 貪婪匹配易導致跨標籤錯誤;改用 [^>]+ 限制在單一標籤內,並明確列出允許副檔名,支援 WebP 等現代格式。
若列表頁需顯示多篇文章縮圖,建議在儲存/更新文章時預先解析並存入欄位 first_image,讀取時直接使用,避免每次請求都跑正則。
function normalize_image_url($url, $cdnDomain = '') {
if (strpos($url, 'http') === 0) return $url; // 已是絕對路徑
if ($cdnDomain && strpos($url, '/') === 0) return $cdnDomain . $url;
return $url; // 相對路徑保持原樣
}
現代前端常用 data-src 延遲載入,可擴展正則:
$pattern = '/<img[^>]+(?:src|data-src)=[\'"]([^\'"]+\.(?:gif|jpg|jpeg|png|webp))[\'"][^>]*>/i';
若內容來自用戶輸入(如富文本編輯器),建議搭配 HTMLPurifier 淨化後再解析,防止 XSS。
建立 application/helpers/image_helper.php (CI) 或通用函數檔:
<?php
if (!function_exists('get_article_thumb')) {
function get_article_thumb($html, $options = []) {
$defaults = [
'default_dir' => 'assets/images/placeholder/',
'random' => true,
'count' => 4,
'extensions' => ['gif','jpg','jpeg','png','webp'],
'attr' => ['src', 'data-src', 'data-original'],
];
$opt = array_merge($defaults, $options);
$ext = implode('|', $opt['extensions']);
$attr = implode('|', $opt['attr']);
$pattern = "/<img[^>]+(?:{$attr})=[\'\"]([^\'\">]+\.(?:{$ext}))[\'\">]/i";
if (preg_match($pattern, $html, $m)) return $m[1];
if ($opt['random']) {
return $opt['default_dir'] . mt_rand(1, $opt['count']) . '.jpg';
}
return $opt['default_dir'] . 'default.jpg';
}
}
提取首圖是常見需求,關鍵在於:正則健壯性(支援各種屬性寫法)、回退策略靈活(隨機/固定/CDN)、效能優化(寫入時預處理)。依專案規模選擇即時解析或預存欄位,並注意內容安全與現代圖片格式支援。