save_post/publish_post钩子无法触发自定义函数问题求助
问题分析与解决方案
核心问题:is_single()条件拦截了钩子触发逻辑
publish_post钩子在后台发布/更新文章时触发,而is_single()是前台判断是否为单篇文章页面的函数,在后台环境下返回false,你的函数一开始就被这个条件拦住,根本没执行后续逻辑。
其他问题点
- 依赖全局
$post对象,钩子触发时上下文可能不一致,不如直接用传入的$post_id获取文章内容更可靠 - 重复给
$post_id赋值,函数参数已经提供了该值 - 未处理
preg_match_all匹配失败的情况,会出现Undefined offset错误 media_sideload_image返回值未做错误校验,可能导致无效ID传入设置逻辑
修正后的代码
function catch_that_image($post_id) { // 跳过自动保存和修订版本,避免重复执行 if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) { return; } // 通过post_id获取文章对象,替代全局$post,保证上下文正确 $post = get_post($post_id); if (!$post) { return; } // 已有特色图则直接返回 if (has_post_thumbnail($post_id)) { return; } $first_img = ''; // 修正正则表达式的转义符号(原代码是HTML转义后的<,PHP中直接用<) $output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches); // 检查匹配结果是否有效,避免Undefined offset错误 if (!empty($matches[1][0])) { $first_img = $matches[1][0]; } // 未匹配到图片则使用默认图 if (empty($first_img)) { $first_img = "https://images.arabicpdfs.com/المكتبة-المفتوحة.jpg"; } // 引入媒体处理必要文件 require_once(ABSPATH . 'wp-admin/includes/media.php'); require_once(ABSPATH . 'wp-admin/includes/file.php'); require_once(ABSPATH . 'wp-admin/includes/image.php'); $desc = "image description"; // 加载图片并获取附件ID $attachment_id = media_sideload_image($first_img, $post_id, $desc, 'id'); // 校验是否成功获取附件ID,再设置为特色图 if (!is_wp_error($attachment_id)) { set_post_thumbnail($post_id, $attachment_id); } } add_action('publish_post', 'catch_that_image', 10, 1);
关键修改说明
- 移除
is_single()判断,确保后台触发钩子时能执行完整逻辑 - 增加自动保存/修订版本跳过逻辑,避免重复执行导致资源浪费
- 用
get_post($post_id)获取文章对象,避免全局变量的上下文问题 - 修正正则表达式的转义符号,保证匹配逻辑生效
- 增加匹配结果和返回值的有效性检查,避免报错
- 完善错误处理,确保只有在成功获取附件ID时才设置特色图
内容的提问来源于stack exchange,提问作者Seal Sealt
相关产品推荐
相关产品推荐

