CMS/門戶網站需在多處調用廣告:側邊欄、內文插入、彈窗等。要求:
document.write JS 輸出兩種模式(便於靜態頁面引入)。Adv::getContentById(35),無需實例化,全局唯一狀態管理。getContent()。<img> 或完整 <object>+<embed> Flash 代碼(含透明模式、點擊跳轉)。addslashes() 轉義雙引號、反斜槓,確保 document.write 不報錯。<?php
class Adv {
private static $id = 0;
private static $order = 0;
private static $isJs = false;
// === 公共入口 ===
public static function getContentById(int $id): string {
self::$id = $id;
return self::getContent();
}
public static function getContentByIdJS(int $id): string {
self::$id = $id;
self::$isJs = true;
return self::getContent();
}
public static function getContentByOrder(int $order): string {
self::$order = $order;
return self::getContent();
}
public static function getContentByOrderJS(int $order): string {
self::$order = $order;
self::$isJs = true;
return self::getContent();
}
// === 核心邏輯 ===
private static function getContent(): string {
// 1. 構建 SQL
$sql = "SELECT `pic`, `width`, `height`, `url` FROM `" . TABLE_ADV . "` ";
if (self::$id) {
$sql .= "WHERE `id` = " . (int)self::$id;
} else {
$sql .= "WHERE `order` = " . (int)self::$order . " ORDER BY `id` DESC";
}
$sql .= " LIMIT 1";
// 2. 執行查詢(假設 Database::Get() 返回單例 PDO 包裝器)
$db = Database::Get();
$db->SqlStr = $sql;
if (!$db->Query() || empty($db->ResultArr)) {
self::reset();
return '';
}
$row = $db->ResultArr[0];
[$file, $width, $height, $url] = $row;
// 3. 判斷素材類型
$ext = strtoupper(pathinfo($file, PATHINFO_EXTENSION));
$html = '';
if ($ext === 'SWF') {
// Flash 廣告:現代瀏覽器已棄用,此處保留邏輯供遷移參考
$html = self::buildFlashHtml($file, $width, $height, $url);
} else {
// 圖片廣告:響應式、語義化
$html = '<a href="' . htmlspecialchars($url, ENT_QUOTES) . '" target="_blank" rel="noopener">';
$html .= '<img src="' . htmlspecialchars($file, ENT_QUOTES) . '" width="' . (int)$width . '" height="' . (int)$height . '" alt="Ad" loading="lazy" />';
$html .= '</a>';
}
// 4. JS 模式轉義
if (self::$isJs) {
$html = 'document.write("' . addslashes($html) . '");';
}
// 5. 重置狀態並返回
self::reset();
return $html;
}
private static function buildFlashHtml(string $file, int $w, int $h, string $url): string {
// 簡化版:實際生產建議用 JS 庫 (如 swfobject) 動態嵌入
return '<object type="application/x-shockwave-flash" data="' . htmlspecialchars($file) . '" width="' . $w . '" height="' . $h . '">'
. '<param name="movie" value="' . htmlspecialchars($file) . '" />'
. '<param name="wmode" value="transparent" />'
. '<param name="quality" value="high" />'
. '<a href="' . htmlspecialchars($url) . '" target="_blank"><img src="' . htmlspecialchars($file) . '" width="' . $w . '" height="' . $h . '" alt="Flash Ad" /></a>'
. '</object>';
}
private static function reset(): void {
self::$id = 0;
self::$order = 0;
self::$isJs = false;
}
}
<!-- 直接輸出 HTML -->
<div class="sidebar-ad">
<?php echo Adv::getContentById(5); ?>
</div>
<!-- 靜態頁面引入 JS -->
<script src="?mod=adv&id=5&output=js"></script>
<!-- 後端路由處理:output=js 時調用 Adv::getContentByIdJS() -->
<video> 或 <img>。DatabaseInterface,便於單元測試(Mock DB)。adv:{id},TTL 5 分鐘,減輕 DB 壓力。data-ad-id,前端 JS 上報曝光;點擊跳轉經中轉頁 /ad/click?id=xxx 記錄點擊再 302 跳目標。該類展示了 PHP 早期「工具類」設計模式:靜態門面 + 內部單例狀態 + 多入口統一核心。雖然 Flash 邏輯已過時,但「素材類型自適應、雙輸出模式、狀態隔離」的思想在現代廣告 SDK、組件庫中依然通用。