如何通过JavaScript调用WordPress短代码执行PHP实现动态直播横幅
问题
我有一段实现YouTube频道直播时显示横幅的WordPress短代码PHP片段,需要该PHP频繁执行(最好用户每次加载页面时都调用)。代码如下:
$ytchannelID = "[YT Channel ID here"; $ytliveurl = "https://www.youtube.com/channel/".$ytchannelID."/live"; $ytchannelLIVE = '"isLive":true'; $contents = file_get_contents($ytliveurl); $start = strpos($contents, '<meta name="title" content="') + 28; $length = strpos($contents, '"><meta name="description" content="') - $start; $src = substr($contents, $start, $length); if ( strpos($contents, $ytchannelLIVE) !== false ){echo '<style type="text/css" media="screen"> * { margin: 0; padding: 0; } div#banner { top: 0; left: 0; background-color: #FFFF00; width: 100%; } div#banner-content { width: 100%; margin: 0 auto; padding: 5px; border: 1px solid #000; text-align: center; font-family: "Permanent Marker"; } </style> <div id="banner"> <div id="banner-content"> 🔴 Channel is live! 🔴 <a href="[watch url here]" style="color: #000FFF;">Tune in now: ' . $src . '</a></div> </div>';} else {echo '<div id="banner"> <div id="banner-content"></div> </div>';} unset($ytliveurl);
这段PHP功能正常,但必须禁用页面缓存,否则直播横幅会持续显示或无法实时更新(因输出HTML被缓存而非执行服务器端PHP)。我的设想是使用可缓存的JavaScript调用该短代码对应的PHP函数,只需执行类似do_shortcode('[wpcode id="1238"]')的调用即可。
请问该方案是否可行?是否应该采用?若可行,具体如何实现?我需要在页面缓存的情况下仍能动态显示/隐藏横幅,即在静态缓存页面中实现动态内容。
方案分析与实现步骤
可行性与必要性
这个方案完全可行,且非常推荐采用。核心逻辑是:静态缓存页面仅包含触发请求的JS代码,用户每次加载页面时,JS都会主动向服务器发起新请求获取最新直播状态,完美绕过页面缓存的限制——既保留了缓存带来的性能优势,又能实现直播状态的实时更新,是缓存环境下动态内容的标准实现方式。
具体实现步骤
1. 封装PHP为AJAX接口(替代直接调用短代码)
直接调用短代码的思路不够高效,更合理的做法是将直播状态检测逻辑封装为WordPress AJAX接口,这样JS可以直接请求这个接口获取动态内容:
function check_yt_live_status() { // 替换为你的YouTube频道ID(修正原代码的引号错误) $ytchannelID = "UCxxxxxxxxx"; $ytliveurl = "https://www.youtube.com/channel/" . $ytchannelID . "/live"; $ytchannelLIVE = '"isLive":true'; // 使用WordPress内置HTTP请求函数,比file_get_contents更可靠且符合规范 $response = wp_remote_get($ytliveurl, array( 'timeout' => 5, // 设置5秒超时,避免阻塞服务器 )); // 请求失败时返回空内容 if (is_wp_error($response)) { echo ''; wp_die(); } $contents = wp_remote_retrieve_body($response); $start = strpos($contents, '<meta name="title" content="') + 28; $length = strpos($contents, '"><meta name="description" content="') - $start; $src = substr($contents, $start, $length); $output = ''; if (strpos($contents, $ytchannelLIVE) !== false) { // 可直接使用$ytliveurl作为观看链接,YouTube会自动跳转当前直播 $watch_url = $ytliveurl; $output = '<style type="text/css" media="screen"> div#banner { top: 0; left: 0; background-color: #FFFF00; width: 100%; } div#banner-content { width: 100%; margin: 0 auto; padding: 5px; border: 1px solid #000; text-align: center; font-family: "Permanent Marker"; } </style> <div id="banner"> <div id="banner-content"> 🔴 频道正在直播!🔴 <a href="' . esc_url($watch_url) . '" style="color: #000FFF;">立即观看:' . esc_html($src) . '</a></div> </div>'; } else { $output = '<div id="banner"><div id="banner-content"></div></div>'; } // 可选:添加本地缓存,10分钟更新一次,减少服务器负载和YouTube请求 set_transient('yt_live_status_' . $ytchannelID, $output, 600); echo $output; wp_die(); // 必须调用,结束AJAX请求 } // 注册AJAX接口,允许前台未登录用户访问 add_action('wp_ajax_nopriv_check_yt_live', 'check_yt_live_status'); add_action('wp_ajax_check_yt_live', 'check_yt_live_status');
将上述代码添加到你的主题functions.php文件中,或通过自定义代码插件添加。
2. 添加前端JS请求动态内容
在页面中插入以下JS代码(可添加到主题footer.php、自定义HTML区块,或通过自定义代码插件的前端脚本功能添加):
document.addEventListener('DOMContentLoaded', function() { // 创建横幅容器,插入到页面最顶部 var bannerContainer = document.createElement('div'); bannerContainer.id = 'yt-live-banner-container'; document.body.insertBefore(bannerContainer, document.body.firstChild); // 发起AJAX请求获取横幅内容 fetch('/wp-admin/admin-ajax.php?action=check_yt_live') .then(response => response.text()) .then(html => { bannerContainer.innerHTML = html; }) .catch(error => { console.error('加载直播横幅失败:', error); }); });
这段代码会在页面加载完成后,自动请求AJAX接口并渲染横幅内容。
3. (可选)用短代码封装JS
如果你习惯用短代码插入功能,可以将上述JS封装为短代码,这样在页面编辑器中插入[yt_live_banner]即可:
function yt_live_banner_shortcode() { ob_start(); ?> <script> document.addEventListener('DOMContentLoaded', function() { var bannerContainer = document.createElement('div'); bannerContainer.id = 'yt-live-banner-container'; document.body.insertBefore(bannerContainer, document.body.firstChild); fetch('/wp-admin/admin-ajax.php?action=check_yt_live') .then(response => response.text()) .then(html => { bannerContainer.innerHTML = html; }) .catch(error => { console.error('加载直播横幅失败:', error); }); }); </script> <?php return ob_get_clean(); } add_shortcode('yt_live_banner', 'yt_live_banner_shortcode');
注意事项
- 缓存排除:确保你的服务器/CDN缓存规则中,排除
/wp-admin/admin-ajax.php?action=check_yt_live这个URL,避免AJAX响应被缓存。 - 安全优化:代码中使用了
esc_url()和esc_html()做转义,避免XSS攻击,不要省略这些安全处理。 - 性能优化:通过
set_transient()添加的本地缓存可以根据需求调整时长(比如5分钟=300秒),平衡实时性和服务器负载。
内容的提问来源于stack exchange,提问作者Atra1n2

