ACF自定义字段类型:input_admin_enqueue_scripts回调函数未触发求助
ACF自定义字段:通过YouTube ID调用API填充字段 + 解决
input_admin_enqueue_scripts不加载JS问题 一、核心问题解决:input_admin_enqueue_scripts不触发
ACF 5+版本要求自定义字段通过继承ACF_Field基类实现,input_admin_enqueue_scripts是类的内置方法,只要注册逻辑正确就会自动触发。常见错误点:
- 未正确继承
ACF_Field类 - JS文件使用相对路径(必须用绝对URL)
- 未调用
acf_register_field_type()完成字段注册
二、完整实现代码
1. PHP字段类型注册文件(示例命名:youtube-video-field.php)
<?php /* Plugin Name: ACF YouTube Video Field Description: 自定义ACF字段,通过YouTube ID拉取视频详情 Version: 1.0 */ if( ! defined( 'ABSPATH' ) ) exit; class ACF_Field_YouTube_Video extends ACF_Field { public function initialize() { // 字段基础配置 $this->name = 'youtube_video'; $this->label = __('YouTube视频详情', 'acf-youtube-video'); $this->category = 'content'; $this->defaults = array( 'youtube_api_key' => '', ); } // 渲染字段设置项(添加API密钥配置) public function render_field_settings( $field ) { acf_render_field_setting( $field, array( 'label' => __('YouTube API密钥', 'acf-youtube-video'), 'instructions' => __('输入你的YouTube Data API v3密钥', 'acf-youtube-video'), 'type' => 'text', 'name' => 'youtube_api_key', )); } // 渲染字段输入界面 public function render_field( $field ) { ?> <div class="acf-youtube-video-field"> <div class="acf-input-wrap"> <label><?php _e('YouTube ID', 'acf-youtube-video'); ?></label> <input type="text" name="<?php echo esc_attr($field['name']); ?>[youtube_id]" value="<?php echo esc_attr($field['value']['youtube_id'] ?? ''); ?>" class="youtube-id-input" /> </div> <button type="button" class="button button-primary fetch-youtube-data" data-api-key="<?php echo esc_attr($field['youtube_api_key']); ?>"> <?php _e('拉取视频详情', 'acf-youtube-video'); ?> </button> <div class="youtube-details-fields" style="margin-top: 20px; padding-top: 20px; border-top: 1px solid #eee;"> <div class="acf-input-wrap"> <label><?php _e('标题', 'acf-youtube-video'); ?></label> <input type="text" name="<?php echo esc_attr($field['name']); ?>[title]" value="<?php echo esc_attr($field['value']['title'] ?? ''); ?>" class="youtube-title" readonly /> </div> <div class="acf-input-wrap" style="margin-top: 10px;"> <label><?php _e('描述', 'acf-youtube-video'); ?></label> <textarea name="<?php echo esc_attr($field['name']); ?>[description]" class="youtube-description" readonly><?php echo esc_textarea($field['value']['description'] ?? ''); ?></textarea> </div> <div class="acf-input-wrap" style="margin-top: 10px;"> <label><?php _e('缩略图URL', 'acf-youtube-video'); ?></label> <input type="text" name="<?php echo esc_attr($field['name']); ?>[thumbnail_url]" value="<?php echo esc_attr($field['value']['thumbnail_url'] ?? ''); ?>" class="youtube-thumbnail" readonly /> </div> <div class="acf-input-wrap" style="margin-top: 10px;"> <label><?php _e('上传日期', 'acf-youtube-video'); ?></label> <input type="text" name="<?php echo esc_attr($field['name']); ?>[upload_date]" value="<?php echo esc_attr($field['value']['upload_date'] ?? ''); ?>" class="youtube-upload-date" readonly /> </div> <div style="display: flex; gap: 10px; margin-top: 10px;"> <div class="acf-input-wrap"> <label><?php _e('时长(分钟)', 'acf-youtube-video'); ?></label> <input type="number" name="<?php echo esc_attr($field['name']); ?>[duration_minutes]" value="<?php echo esc_attr($field['value']['duration_minutes'] ?? 0); ?>" class="youtube-duration-minutes" readonly /> </div> <div class="acf-input-wrap"> <label><?php _e('时长(秒)', 'acf-youtube-video'); ?></label> <input type="number" name="<?php echo esc_attr($field['name']); ?>[duration_seconds]" value="<?php echo esc_attr($field['value']['duration_seconds'] ?? 0); ?>" class="youtube-duration-seconds" readonly /> </div> </div> </div> </div> <?php } // 加载JS/CSS资源 public function input_admin_enqueue_scripts() { // 用绝对URL加载JS,确保路径正确 $script_url = plugin_dir_url(__FILE__) . 'youtube-video-field.js'; wp_enqueue_script('acf-youtube-video-field', $script_url, array('acf-input'), '1.0', true); } // 保存字段数据 public function update_value( $value, $post_id, $field ) { return array( 'youtube_id' => sanitize_text_field($value['youtube_id'] ?? ''), 'title' => sanitize_text_field($value['title'] ?? ''), 'description' => sanitize_textarea_field($value['description'] ?? ''), 'thumbnail_url' => esc_url_raw($value['thumbnail_url'] ?? ''), 'upload_date' => sanitize_text_field($value['upload_date'] ?? ''), 'duration_minutes' => intval($value['duration_minutes'] ?? 0), 'duration_seconds' => intval($value['duration_seconds'] ?? 0), ); } } // 注册字段类型 add_action('acf/include_field_types', function() { new ACF_Field_YouTube_Video(); }); // AJAX处理:拉取YouTube视频数据 add_action('wp_ajax_acf_fetch_youtube_video', 'acf_fetch_youtube_video_data'); function acf_fetch_youtube_video_data() { check_ajax_referer('acf_nonce', 'nonce'); $youtube_id = sanitize_text_field($_POST['youtube_id']); $api_key = sanitize_text_field($_POST['api_key']); if( empty($youtube_id) || empty($api_key) ) { wp_send_json_error(array('message' => '缺少YouTube ID或API密钥')); } // 调用YouTube API $api_url = "https://www.googleapis.com/youtube/v3/videos?id={$youtube_id}&key={$api_key}&part=snippet,contentDetails"; $response = wp_remote_get($api_url); if( is_wp_error($response) ) { wp_send_json_error(array('message' => '拉取视频数据失败')); } $body = wp_remote_retrieve_body($response); $data = json_decode($body, true); if( empty($data['items']) ) { wp_send_json_error(array('message' => '未找到该ID对应的视频')); } $video = $data['items'][0]; $snippet = $video['snippet']; $content_details = $video['contentDetails']; // 解析ISO 8601格式时长为分钟和秒 preg_match('/PT(\d+H)?(\d+M)?(\d+S)?/', $content_details['duration'], $matches); $hours = isset($matches[1]) ? intval(str_replace('H', '', $matches[1])) : 0; $minutes = isset($matches[2]) ? intval(str_replace('M', '', $matches[2])) : 0; $seconds = isset($matches[3]) ? intval(str_replace('S', '', $matches[3])) : 0; $total_minutes = $hours * 60 + $minutes; wp_send_json_success(array( 'title' => $snippet['title'], 'description' => $snippet['description'], 'thumbnail_url' => $snippet['thumbnails']['high']['url'], 'upload_date' => date('Y-m-d H:i:s', strtotime($snippet['publishedAt'])), 'duration_minutes' => $total_minutes, 'duration_seconds' => $seconds, )); }
2. JS交互文件(youtube-video-field.js)
(function($) { $(document).on('click', '.fetch-youtube-data', function(e) { e.preventDefault(); var $button = $(this); var $fieldWrap = $button.closest('.acf-youtube-video-field'); var youtubeId = $fieldWrap.find('.youtube-id-input').val().trim(); var apiKey = $button.data('api-key'); if( !youtubeId ) { alert('请输入YouTube ID'); return; } if( !apiKey ) { alert('请在字段设置中配置YouTube API密钥'); return; } // 加载状态处理 $button.prop('disabled', true).text('拉取中...'); // 发送AJAX请求 $.ajax({ url: acf.get('ajaxurl'), type: 'POST', data: { action: 'acf_fetch_youtube_video', youtube_id: youtubeId, api_key: apiKey, nonce: acf.get('nonce') }, success: function(response) { if( response.success ) { var data = response.data; // 填充字段 $fieldWrap.find('.youtube-title').val(data.title); $fieldWrap.find('.youtube-description').val(data.description); $fieldWrap.find('.youtube-thumbnail').val(data.thumbnail_url); $fieldWrap.find('.youtube-upload-date').val(data.upload_date); $fieldWrap.find('.youtube-duration-minutes').val(data.duration_minutes); $fieldWrap.find('.youtube-duration-seconds').val(data.duration_seconds); } else { alert(response.data.message || '拉取视频数据失败'); } }, error: function() { alert('拉取数据时发生错误'); }, complete: function() { $button.prop('disabled', false).text('拉取视频详情'); } }); }); })(jQuery);
三、关键注意事项
- API密钥配置:需在Google Cloud控制台创建并启用YouTube Data API v3密钥,确保密钥权限正确。
- 路径正确性:
input_admin_enqueue_scripts中必须使用绝对URL加载JS,避免因相对路径导致的404错误。 - 版本兼容:代码基于ACF 5+版本,若使用ACF 4需改用旧版字段注册方式。
- 安全验证:AJAX请求使用ACF内置nonce验证,避免恶意请求。
内容的提问来源于stack exchange,提问作者luna moonfang
相关产品推荐
相关产品推荐

