WordPress插件开发:如何检测文件变更并自动提交至GitHub
检测WordPress站点文件变更并自动提交到GitHub的解决方案
一、用WordPress钩子捕捉实时文件操作
如果只需要监控后台主动修改的文件(比如主题编辑器改代码、插件编辑器改文件、上传媒体),可以直接用WP内置的动作钩子,无需全量扫描:
- 主题/插件编辑器修改:后台编辑主题或插件文件后,会触发对应的
admin_post_钩子:
// 监听主题文件编辑提交 add_action('admin_post_edit-theme-file', 'trigger_github_commit'); // 监听插件文件编辑提交 add_action('admin_post_edit-plugin-file', 'trigger_github_commit'); function trigger_github_commit() { // 这里调用你已有的GitHub提交逻辑 // commit_to_github(); }
- 媒体文件上传:文件上传完成后触发
wp_handle_upload钩子:
add_action('wp_handle_upload', function($upload_data) { // 上传完成后执行提交 // commit_to_github(); return $upload_data; // 必须返回原数据,不干扰WP默认流程 });
- 主题自定义修改:主题自定义设置变更时触发
update_option_theme_mods_{$stylesheet}:
add_action('update_option_theme_mods_' . get_stylesheet(), 'trigger_github_commit');
二、自定义全量文件哈希扫描(覆盖所有文件变更)
如果要监控包括FTP修改、外部工具修改的文件,就得定时扫描并对比文件哈希值,步骤如下:
1. 初始化哈希存储(插件激活时执行)
首次激活插件时,遍历目标目录计算所有文件的MD5哈希,存在WP选项里:
function init_site_file_hashes() { // 定义需要监控的目录(根据需求调整,建议排除uploads等动态目录) $target_dirs = [ ABSPATH . 'wp-content/themes', ABSPATH . 'wp-content/plugins', ABSPATH . 'wp-includes', ABSPATH . 'wp-admin' ]; $file_hashes = []; foreach ($target_dirs as $dir) { if (!is_dir($dir)) continue; // 递归遍历目录 $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS) ); foreach ($iterator as $file) { if (!$file->isFile()) continue; $file_path = $file->getPathname(); // 排除临时文件、缓存、日志(可自行扩展规则) if (preg_match('/\.(tmp|cache|log|bak)$/i', $file_path)) continue; $file_hashes[$file_path] = md5_file($file_path); } } update_option('site_monitored_file_hashes', $file_hashes); } register_activation_hook(__FILE__, 'init_site_file_hashes');
2. 定时扫描对比变更
用WP Cron定时执行扫描,对比当前文件哈希和存储的哈希,发现变更则触发提交:
function check_for_file_changes() { $stored_hashes = get_option('site_monitored_file_hashes', []); $target_dirs = [ ABSPATH . 'wp-content/themes', ABSPATH . 'wp-content/plugins', ABSPATH . 'wp-includes', ABSPATH . 'wp-admin' ]; $has_changes = false; $new_hashes = []; // 检查新增/修改的文件 foreach ($target_dirs as $dir) { if (!is_dir($dir)) continue; $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS) ); foreach ($iterator as $file) { if (!$file->isFile()) continue; $file_path = $file->getPathname(); if (preg_match('/\.(tmp|cache|log|bak)$/i', $file_path)) continue; $current_hash = md5_file($file_path); $new_hashes[$file_path] = $current_hash; // 对比哈希或检查是否为新增文件 if (!isset($stored_hashes[$file_path]) || $stored_hashes[$file_path] !== $current_hash) { $has_changes = true; } } } // 检查是否有文件被删除 foreach ($stored_hashes as $file_path => $_) { if (!file_exists($file_path)) { $has_changes = true; break; } } if ($has_changes) { // 执行你的GitHub提交逻辑 // commit_to_github(); // 更新存储的哈希值 update_option('site_monitored_file_hashes', $new_hashes); } } // 注册定时任务(每小时执行一次,可调整为daily/weekly) add_action('wp', function() { if (!wp_next_scheduled('site_file_scan_hook')) { wp_schedule_event(time(), 'hourly', 'site_file_scan_hook'); } }); add_action('site_file_scan_hook', 'check_for_file_changes');
三、关键优化点
- 排除无关目录:务必排除
wp-content/uploads、缓存目录、备份文件,避免不必要的提交和性能损耗 - 性能控制:不要设置过短的扫描间隔,小时级扫描足够应对大部分场景;大站点可以分目录分批扫描
- 权限验证:确保PHP进程有读取所有监控文件的权限,GitHub API Token需要仓库的写入权限
- 避免重复提交:可以额外存储最后提交时间,扫描时只检查修改时间晚于最后提交时间的文件
内容的提问来源于stack exchange,提问作者Meet Bhadeshia
相关产品推荐
相关产品推荐

