配置音乐播放器的基本参数。获取网易云歌单ID:打开网易云音乐网页版,在歌单页面URL中找到”id=”后面的数字。
使用短代码
可以在文章或页面中插入播放器。可以使用参数覆盖全局设置,例如:
🛠️ 完整插件代码
请将以下代码保存为 custom-music-player.php
。此版本重点强化了数据验证、权限检查和错误处理。
<?php
/**
* Plugin Name: 老苏博客音乐播放器 (强力修复版)
* Description: 使用APlayer和MetingJS为网站添加音乐播放器,支持自动播放、PJAX刷新和短代码插入。
* Version: 2.0
* Author: 老苏博客
* Text Domain: custom-music-player
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 插件激活时设置默认选项
function cmp_activate() {
$default_options = array(
'cmp_global_enable' => 1,
'cmp_server' => 'netease',
'cmp_type' => 'playlist',
'cmp_id' => '',
'cmp_autoplay' => 0,
'cmp_fixed' => 0,
'cmp_volume' => '0.7'
);
if (false === get_option('cmp_settings')) {
add_option('cmp_settings', $default_options);
}
// 确保选项初始值已写入数据库
update_option('cmp_settings', $default_options);
}
register_activation_hook(__FILE__, 'cmp_activate');
// 添加后台设置菜单
function cmp_add_admin_menu() {
add_options_page(
__('音乐播放器设置', 'custom-music-player'),
__('音乐播放器', 'custom-music-player'),
'manage_options',
'custom_music_player',
'cmp_options_page'
);
}
add_action('admin_menu', 'cmp_add_admin_menu');
// 注册设置
function cmp_settings_init() {
register_setting(
'cmp_plugin',
'cmp_settings',
array(
'sanitize_callback' => 'cmp_sanitize_settings',
'default' => array(
'cmp_global_enable' => 1,
'cmp_server' => 'netease',
'cmp_type' => 'playlist',
'cmp_id' => '',
'cmp_autoplay' => 0,
'cmp_fixed' => 0,
'cmp_volume' => '0.7'
)
)
);
add_settings_section(
'cmp_plugin_section',
__('全局播放器设置', 'custom-music-player'),
'cmp_settings_section_callback',
'cmp_plugin'
);
add_settings_field(
'cmp_global_enable',
__('启用全局播放器', 'custom-music-player'),
'cmp_global_enable_render',
'cmp_plugin',
'cmp_plugin_section'
);
add_settings_field(
'cmp_server',
__('默认音乐平台', 'custom-music-player'),
'cmp_server_render',
'cmp_plugin',
'cmp_plugin_section'
);
add_settings_field(
'cmp_type',
__('默认类型', 'custom-music-player'),
'cmp_type_render',
'cmp_plugin',
'cmp_plugin_section'
);
add_settings_field(
'cmp_id',
__('默认歌单/歌曲ID', 'custom-music-player'),
'cmp_id_render',
'cmp_plugin',
'cmp_plugin_section'
);
add_settings_field(
'cmp_autoplay',
__('默认自动播放', 'custom-music-player'),
'cmp_autoplay_render',
'cmp_plugin',
'cmp_plugin_section'
);
add_settings_field(
'cmp_fixed',
__('默认固定底部', 'custom-music-player'),
'cmp_fixed_render',
'cmp_plugin',
'cmp_plugin_section'
);
add_settings_field(
'cmp_volume',
__('默认音量', 'custom-music-player'),
'cmp_volume_render',
'cmp_plugin',
'cmp_plugin_section'
);
}
add_action('admin_init', 'cmp_settings_init');
// 数据清理和验证回调函数 - 关键修复部分
function cmp_sanitize_settings($input) {
$output = get_option('cmp_settings', array());
$errors = array();
// 验证并清理每个字段
if (isset($input['cmp_global_enable'])) {
$output['cmp_global_enable'] = ($input['cmp_global_enable'] == 1) ? 1 : 0;
} else {
$output['cmp_global_enable'] = 0; // 关键修复:复选框未提交时设置为0
}
if (isset($input['cmp_server'])) {
$allowed_servers = array('netease', 'tencent', 'xiami');
$output['cmp_server'] = in_array($input['cmp_server'], $allowed_servers) ? $input['cmp_server'] : 'netease';
}
if (isset($input['cmp_type'])) {
$allowed_types = array('playlist', 'song', 'album');
$output['cmp_type'] = in_array($input['cmp_type'], $allowed_types) ? $input['cmp_type'] : 'playlist';
}
if (isset($input['cmp_id'])) {
$output['cmp_id'] = sanitize_text_field($input['cmp_id']);
}
if (isset($input['cmp_autoplay'])) {
$output['cmp_autoplay'] = ($input['cmp_autoplay'] == 1) ? 1 : 0;
} else {
$output['cmp_autoplay'] = 0;
}
if (isset($input['cmp_fixed'])) {
$output['cmp_fixed'] = ($input['cmp_fixed'] == 1) ? 1 : 0;
} else {
$output['cmp_fixed'] = 0;
}
if (isset($input['cmp_volume'])) {
$volume = floatval($input['cmp_volume']);
// 确保音量在0到1之间
$output['cmp_volume'] = ($volume >= 0 && $volume <= 1) ? strval($volume) : '0.7';
}
// 如果有错误,可以在这里处理
if (!empty($errors)) {
add_settings_error(
'cmp_settings',
'cmp_settings_error',
__('设置保存时出现错误,请检查输入。', 'custom-music-player'),
'error'
);
}
return $output;
}
// 设置字段渲染函数
function cmp_global_enable_render() {
$options = get_option('cmp_settings', array());
$enabled = isset($options['cmp_global_enable']) ? $options['cmp_global_enable'] : 1;
?>
<input type="checkbox" name="cmp_settings[cmp_global_enable]" value="1" <?php checked(1, $enabled, true); ?>>
<label><?php _e('在网站底部显示全局播放器(仍可使用短代码在其他位置添加)', 'custom-music-player'); ?></label>
<?php
}
function cmp_server_render() {
$options = get_option('cmp_settings', array());
$server = isset($options['cmp_server']) ? $options['cmp_server'] : 'netease';
?>
<select name="cmp_settings[cmp_server]">
<option value="netease" <?php selected($server, 'netease'); ?>><?php _e('网易云音乐', 'custom-music-player'); ?></option>
<option value="tencent" <?php selected($server, 'tencent'); ?>><?php _e('QQ音乐', 'custom-music-player'); ?></option>
<option value="xiami" <?php selected($server, 'xiami'); ?>><?php _e('虾米音乐', 'custom-music-player'); ?></option>
</select>
<?php
}
function cmp_type_render() {
$options = get_option('cmp_settings', array());
$type = isset($options['cmp_type']) ? $options['cmp_type'] : 'playlist';
?>
<select name="cmp_settings[cmp_type]">
<option value="playlist" <?php selected($type, 'playlist'); ?>><?php _e('歌单', 'custom-music-player'); ?></option>
<option value="song" <?php selected($type, 'song'); ?>><?php _e('单曲', 'custom-music-player'); ?></option>
<option value="album" <?php selected($type, 'album'); ?>><?php _e('专辑', 'custom-music-player'); ?></option>
</select>
<?php
}
function cmp_id_render() {
$options = get_option('cmp_settings', array());
$id = isset($options['cmp_id']) ? $options['cmp_id'] : '';
?>
<input type="text" name="cmp_settings[cmp_id]" value="<?php echo esc_attr($id); ?>" style="width: 300px;">
<p class="description"><?php _e('请输入对应音乐平台的歌单ID、歌曲ID或专辑ID', 'custom-music-player'); ?></p>
<?php
}
function cmp_autoplay_render() {
$options = get_option('cmp_settings', array());
$autoplay = isset($options['cmp_autoplay']) ? $options['cmp_autoplay'] : 0;
?>
<input type="checkbox" name="cmp_settings[cmp_autoplay]" value="1" <?php checked(1, $autoplay, true); ?>>
<label><?php _e('启用自动播放(注意:浏览器可能会阻止自动播放)', 'custom-music-player'); ?></label>
<?php
}
function cmp_fixed_render() {
$options = get_option('cmp_settings', array());
$fixed = isset($options['cmp_fixed']) ? $options['cmp_fixed'] : 0;
?>
<input type="checkbox" name="cmp_settings[cmp_fixed]" value="1" <?php checked(1, $fixed, true); ?>>
<label><?php _e('固定在页面底部', 'custom-music-player'); ?></label>
<?php
}
function cmp_volume_render() {
$options = get_option('cmp_settings', array());
$volume = isset($options['cmp_volume']) ? $options['cmp_volume'] : '0.7';
?>
<input type="number" name="cmp_settings[cmp_volume]" min="0" max="1" step="0.1" value="<?php echo esc_attr($volume); ?>">
<p class="description"><?php _e('请输入0-1之间的数值,如0.7表示70%音量', 'custom-music-player'); ?></p>
<?php
}
function cmp_settings_section_callback() {
echo '<p>' . __('配置音乐播放器的基本参数。获取网易云歌单ID:打开网易云音乐网页版,在歌单页面URL中找到"id="后面的数字。', 'custom-music-player') . '</p>';
echo '<p>' . __('使用短代码 <code>
</code> 可以在文章或页面中插入播放器。可以使用参数覆盖全局设置,例如:<code>
</code>', 'custom-music-player') . '</p>';
}
// 选项页面渲染
function cmp_options_page() {
// 检查用户权限
if (!current_user_can('manage_options')) {
wp_die(__('您没有权限访问此页面。', 'custom-music-player'));
}
// 显示设置错误/更新消息
settings_errors('cmp_settings');
?>
<div class="wrap">
<h1><?php _e('音乐播放器设置', 'custom-music-player'); ?></h1>
<form action="options.php" method="post">
<?php
settings_fields('cmp_plugin');
do_settings_sections('cmp_plugin');
submit_button();
?>
</form>
<div style="margin-top: 30px; padding: 10px; background: #f5f5f5; border-radius: 5px;">
<h3><?php _e('故障排查', 'custom-music-player'); ?></h3>
<p><?php _e('如果设置无法保存,请尝试:', 'custom-music-player'); ?></p>
<ol>
<li><?php _e('禁用其他所有插件,检查是否存在冲突', 'custom-music-player'); ?></li>
<li><?php _e('切换到默认主题(如Twenty Twenty-Four)', 'custom-music-player'); ?></li>
<li><?php _e('检查服务器错误日志(通常在 /var/log/ 目录下)', 'custom-music-player'); ?></li>
<li><?php _e('检查文件权限(文件夹755,文件644)', 'custom-music-player'); ?></li>
</ol>
</div>
</div>
<?php
}
// 注册短代码
function cmp_music_player_shortcode($atts) {
// 获取全局设置
$options = get_option('cmp_settings', array());
// 合并短代码参数和默认设置
$atts = shortcode_atts(array(
'server' => isset($options['cmp_server']) ? $options['cmp_server'] : 'netease',
'type' => isset($options['cmp_type']) ? $options['cmp_type'] : 'playlist',
'id' => isset($options['cmp_id']) ? $options['cmp_id'] : '',
'autoplay' => isset($options['cmp_autoplay']) ? $options['cmp_autoplay'] : 'false',
'fixed' => isset($options['cmp_fixed']) ? $options['cmp_fixed'] : 'false',
'volume' => isset($options['cmp_volume']) ? $options['cmp_volume'] : '0.7',
), $atts);
// 如果未设置ID,返回空
if (empty($atts['id'])) {
return '<p>' . __('请先在播放器设置中配置音乐ID,或使用短代码参数指定。', 'custom-music-player') . '</p>';
}
// 确保布尔值格式正确
$autoplay = ($atts['autoplay'] === 'true' || $atts['autoplay'] === '1' || $atts['autoplay'] === true) ? 'true' : 'false';
$fixed = ($atts['fixed'] === 'true' || $atts['fixed'] === '1' || $atts['fixed'] === true) ? 'true' : 'false';
// 加载必要的CSS和JS
cmp_enqueue_assets();
// 使用输出缓冲捕获播放器HTML
ob_start();
?>
<div class="cmp-player-container">
<meting-js
server="<?php echo esc_attr($atts['server']); ?>"
type="<?php echo esc_attr($atts['type']); ?>"
id="<?php echo esc_attr($atts['id']); ?>"
autoplay="<?php echo $autoplay; ?>"
fixed="<?php echo $fixed; ?>"
volume="<?php echo esc_attr($atts['volume']); ?>"
loop="all"
order="list"
preload="auto">
</meting-js>
</div>
<?php
return ob_get_clean();
}
add_shortcode('music_player', 'cmp_music_player_shortcode');
// 加载CSS和JS资源
function cmp_enqueue_assets() {
wp_enqueue_style('aplayer-css', 'https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css');
wp_enqueue_script('aplayer-js', 'https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js', array(), false, true);
wp_enqueue_script('meting-js', 'https://cdn.jsdelivr.net/npm/meting@2.0.1/dist/Meting.min.js', array('aplayer-js'), false, true);
// 添加PJAX支持
cmp_add_pjax_support();
}
// 添加PJAX支持
function cmp_add_pjax_support() {
?>
<script>
(function($) {
// 监听PJAX完成事件
$(document).on('pjax:end', function() {
if (typeof Meting !== 'undefined') {
// 销毁现有的播放器实例
if (window.aplayers && window.aplayers.length > 0) {
for (var i = 0; i < window.aplayers.length; i++) {
window.aplayers[i].destroy();
}
}
// 重新初始化MetingJS
if (typeof Meting === 'function') {
new Meting();
}
}
});
})(jQuery);
</script>
<?php
}
// 在前台加载全局播放器(如果启用)
function cmp_load_global_player() {
$options = get_option('cmp_settings', array());
// 检查是否启用全局播放器
$global_enable = isset($options['cmp_global_enable']) ? $options['cmp_global_enable'] : 1;
if (!$global_enable) {
return;
}
// 检查必要设置是否存在
if (empty($options['cmp_id']) || empty($options['cmp_server']) || empty($options['cmp_type'])) {
return;
}
// 加载资源
cmp_enqueue_assets();
// 输出播放器HTML
$autoplay = isset($options['cmp_autoplay']) && $options['cmp_autoplay'] ? 'true' : 'false';
$fixed = isset($options['cmp_fixed']) && $options['cmp_fixed'] ? 'true' : 'false';
$volume = isset($options['cmp_volume']) ? $options['cmp_volume'] : '0.7';
echo '<div class="cmp-global-player">';
echo '<meting-js
server="' . esc_attr($options['cmp_server']) . '"
type="' . esc_attr($options['cmp_type']) . '"
id="' . esc_attr($options['cmp_id']) . '"
autoplay="' . $autoplay . '"
fixed="' . $fixed . '"
volume="' . $volume . '"
loop="all"
order="list"
preload="auto">
</meting-js>';
echo '</div>';
}
add_action('wp_footer', 'cmp_load_global_player');
// 添加插件设置链接
function cmp_add_action_links($links) {
$settings_link = '<a href="' . admin_url('options-general.php?page=custom_music_player') . '">' . __('设置', 'custom-music-player') . '</a>';
array_unshift($links, $settings_link);
return $links;
}
add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'cmp_add_action_links');
// 调试函数
function cmp_debug_log($message) {
if (WP_DEBUG === true) {
if (is_array($message) || is_object($message)) {
error_log(print_r($message, true));
} else {
error_log($message);
}
}
}
?>
🔧 主要修复与改进
-
彻底修复复选框保存问题:在
cmp_sanitize_settings
函数中,明确处理了复选框未提交时的情况(如cmp_global_enable
),确保其值能正确设置为0
。 -
增强数据验证:对所有输入数据进行严格的验证和清理,防止无效数据导致问题。
-
完善的错误处理:添加了
settings_errors()
显示,并增加了cmp_debug_log
函数辅助调试。 -
国际化支持:为所有文本添加了国际化函数,为插件翻译做好准备。
-
默认值强化:在
register_setting
和cmp_sanitize_settings
中都确保了默认值的设置。
THE END