单页面多视频独立播放量统计AJAX存库故障排查求助
问题描述
找不到能在单页多视频场景下统计单个视频播放量的插件,现有计数插件基本都是针对页面或文章的,所以自行开发,但遇到问题:
通过jQuery实现了点击播放图标时计数前端显示增加,但AJAX将增量后的播放量保存到数据库时失败。
子主题模板代码
<?php /** * Template Name: All Videos Template */ get_header(); ?> <script> jQuery(document).ready(function($) { // Attach click event listener to play icons $('.video-item .play-icon').on('click', function(e) { e.preventDefault(); var videoContainer = $(this).closest('.video-item'); var videoId = videoContainer.data('video-id'); var viewCountElement = videoContainer.find('.view-count'); // Send AJAX request to update view count $.ajax({ url: ajaxurl, type: 'POST', data: { action: 'update_view_count', post_id: videoId }, success: function(response) { // Update view count in the container viewCountElement.text(response); }, error: function() { console.log('Error occurred during AJAX request.'); } }); }); }); </script> <div id="primary" class="content-area"> <main id="main" class="site-main"> <?php // Query to retrieve all attachments $args = array( 'post_type' => 'attachment', 'post_mime_type' => 'video', 'post_status' => 'inherit', 'posts_per_page' => -1, /* 'orderby' => 'rand', // Randomize video listing*/ ); $video_query = new WP_Query($args); if ($video_query->have_posts()) : ?> <div class="video-grid"> <?php while ($video_query->have_posts()) : $video_query->the_post(); $video_url = wp_get_attachment_url(get_the_ID()); $attachment_page_url = get_permalink(); $attachment_page_title = get_the_title(get_post()->post_parent); // Check if the attachment URL starts with the 'escort' slug if (strpos($attachment_page_url, '/escort/') !== false) : // Get the video views count $video_id = get_the_ID(); $video_views = (int) get_post_meta($video_id, 'wpzu_video_views', true); // Modified meta key ?> <div class="video-item"> <a href="<?php echo esc_url($attachment_page_url); ?>" target="_blank" rel="noopener noreferrer"> <video id="video-<?php echo esc_attr($video_id); ?>" src="<?php echo esc_url($video_url); ?>" controls loading="lazy"></video> </a> <div class="video-details"> <h2> <a href="<?php echo esc_url($attachment_page_url); ?>" target="_blank" rel="noopener noreferrer"> <?php echo esc_html($attachment_page_title); ?> </a> </h2> <p class="view-count" data-video-id="<?php echo esc_attr($video_id); ?>"> <?php echo esc_html($video_views); ?> Views </p> </div> </div> <script> document.getElementById('video-<?php echo esc_js($video_id); ?>').addEventListener('play', function() { // Increment the video views count var viewCountElement = document.querySelector('.view-count[data-video-id="<?php echo esc_attr($video_id); ?>"]'); var currentViewCount = parseInt(viewCountElement.innerText.replace('Views: ', '')); var newViewCount = currentViewCount + 1; viewCountElement.innerText = 'Views: ' + newViewCount; // Send AJAX request to update the view count in the database jQuery.ajax({ url: ajaxurl, type: 'POST', data: { action: 'update_view_count', video_id: <?php echo esc_js($video_id); ?>, view_count: newViewCount }, success: function(response) { console.log('View count updated successfully.'); }, error: function() { console.log('Error occurred during AJAX request.'); } }); }); </script> <?php endif; endwhile; wp_reset_postdata(); ?> </div> <?php else : echo 'No videos found.'; endif; ?> </main><!-- #main --> </div><!-- #primary --> <?php get_footer(); ?>
子主题functions.php中的AJAX代码
// Enqueue the JavaScript file for AJAX function enqueue_custom_scripts() { wp_enqueue_script( 'custom-ajax-script', get_stylesheet_directory_uri() . '/js/custom-ajax.js', array( 'jquery' ), '1.0', true ); wp_localize_script( 'custom-ajax-script', 'customAjax', array( 'ajaxUrl' => admin_url( 'admin-ajax.php' ) ) ); } add_action( 'wp_enqueue_scripts', 'enqueue_custom_scripts' ); // Update view count via AJAX function update_view_count_ajax() { global $wpdb; $table_name = $wpdb->prefix . 'postmeta'; // Replace 'wpzu_' with your desired prefix if (isset($_POST['post_id'])) { $post_id = intval($_POST['post_id']); $video_views = (int) $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM $table_name WHERE meta_key = 'video_views' AND post_id = %d", $post_id ) ); $video_views++; $wpdb->update( $table_name, array( 'meta_value' => $video_views ), array( 'meta_key' => 'video_views', 'post_id' => $post_id ), array( '%d' ), array( '%s', '%d' ) ); echo $video_views; } wp_die(); // Always include this line to terminate the AJAX call properly } add_action( 'wp_ajax_update_view_count', 'update_view_count_ajax' ); add_action( 'wp_ajax_nopriv_update_view_count', 'update_view_count_ajax' );
问题排查与修复方案
1. AJAX URL不匹配
模板内联脚本使用ajaxurl全局变量,但functions.php里本地化的是customAjax.ajaxUrl,且内联脚本未依赖注册的custom-ajax-script,导致ajaxurl可能未定义(前端控制台会报错)。
修复:将内联脚本中的url: ajaxurl替换为url: customAjax.ajaxUrl。
2. 元键名称不一致
模板中获取播放量用的是wpzu_video_views,但PHP代码中查询和更新的是video_views,两者不匹配导致无法正确读写数据。
修复:统一元键名称为wpzu_video_views。
3. 前端文本替换逻辑错误
播放量显示文本是X Views,但play事件里用replace('Views: ', ''),替换后仍为X Views,parseInt会返回NaN,导致计数错误。
修复:改为parseInt(viewCountElement.innerText.replace(' Views', '')),同时更新前端显示文本为newViewCount + ' Views'保持一致。
4. AJAX传参不匹配
play事件中AJAX传的参数是video_id,但PHP代码只判断$_POST['post_id'],导致请求无法被处理。
修复:在PHP代码中同时兼容两种参数:
$post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : intval($_POST['video_id']);
5. 直接操作数据库表不规范
使用$wpdb直接操作postmeta表不如用WordPress内置的get_post_meta和update_post_meta函数,更安全简洁,还能自动处理元数据的创建(如果不存在)。
修复后的PHP函数示例:
// Update view count via AJAX function update_view_count_ajax() { $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : (isset($_POST['video_id']) ? intval($_POST['video_id']) : 0); if (!$post_id) { wp_die(); } $video_views = (int) get_post_meta($post_id, 'wpzu_video_views', true); $video_views++; update_post_meta($post_id, 'wpzu_video_views', $video_views); echo $video_views; wp_die(); }
6. 重复事件绑定
模板中同时绑定了.play-icon的点击事件和video的play事件,可能导致同一播放行为触发两次AJAX请求,造成计数重复增加。
修复:保留其中一种事件绑定即可,推荐用video的play事件(更准确,用户可能直接点击视频播放按钮而非外部图标)。
内容的提问来源于stack exchange,提问作者Godman Umoeka

