本文约 4,674 字,预计阅读 12 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:表单数据是最容易被忽略的「个人信息仓库」
一个跑了两年的站点,表单条目里可能躺着几千条真实姓名、手机号、邮箱,甚至身份证照片和营业执照。它们通常散落在插件自建的数据表、媒体库的上传目录、以及若干封邮件通知里。很少有站长能完整回答三个问题:这些数据存在哪、保存多久、客户要求删除时能不能删干净。
这在过去只是运维习惯问题,现在则是合规问题。面向欧洲用户的站点要满足 GDPR 的「访问权、可携带权、被遗忘权」;面向国内用户的站点,个人信息保护相关法规同样要求「最小必要」与「限期留存」。好消息是,WordPress 内置了个人数据导出与擦除的工具框架,插件也可以通过钩子接入——你要做的只是把它用起来。
原理分析:数据散在四个地方
| 存放位置 | 典型来源 | 清理难点 |
|---|---|---|
| 插件自建数据表 | WPForms、Fluent Forms、FluentCRM 等 | 不在文章表里,容易被备份遗漏 |
| 自定义文章类型 | Flamingo(CF7 的条目存储扩展,使用 flamingo_inbound 等文章类型) |
走回收站机制,需强制删除 |
| 上传目录 | 表单的文件上传字段 | 数据库删了文件还在 |
| 邮件通知 | 通知邮件副本 | 分散在多个邮箱 |
WordPress 的隐私工具位于后台「工具 → 导出个人数据」与「工具 → 擦除个人数据」。它们的工作方式是:管理员输入邮箱发起请求 → 站点收集所有「导出器 / 擦除器」登记的数据 → 生成导出文件或执行删除 → 管理员确认。插件通过 wp_privacy_personal_data_exporters 和 wp_privacy_personal_data_erasers 两个过滤器把自己的数据登记进去。很多表单插件已经登记过,但自建的条目表或自定义开发的表单往往没有登记,这正是本文要补上的部分。
保姆级实操:留存策略 + 自动清理 + 合规导出
步骤1:先盘点数据在哪。 用 SQL 看看各条目表的规模,不要凭感觉。
-- 盘点常见表单插件的条目表规模(表名按实际安装调整)
SELECT 'flamingo_inbound' AS src, COUNT(*) AS cnt FROM wp_posts WHERE post_type = 'flamingo_inbound'
UNION ALL
SELECT 'wpforms_entries', COUNT(*) FROM wp_wpforms_entries
UNION ALL
SELECT 'fluentform_submissions', COUNT(*) FROM wp_fluentform_submissions;
步骤2:制定留存周期并写进隐私政策。 常见做法是:销售线索保留 12 个月,未转化线索 6 个月后删除,含身份证等敏感文件的条目 3 个月内删除。把具体周期写进隐私政策页面,这是合规的基本要求,也是回答客户询问的依据。
步骤3:配置自动清理。 用 WP-CLI 加系统计划任务是最稳的做法,避免依赖 WP-Cron。
# 每周清理一次:删除 180 天前的 Flamingo 条目(含回收站中的)
0 4 * * 1 wp post delete $(wp post list --post_type=flamingo_inbound \
--date_query='before:180 days ago' --format=ids) --force > /dev/null 2>&1
或者用 WordPress 的计划任务在站内执行:
<?php
// 每日清理过期条目(示例:删除 180 天前的 Flamingo 收件)
if ( ! wp_next_scheduled( 'mf_purge_old_entries' ) ) {
wp_schedule_event( time(), 'daily', 'mf_purge_old_entries' );
}
add_action( 'mf_purge_old_entries', function () {
$ids = get_posts( array(
'post_type' => 'flamingo_inbound',
'posts_per_page' => 200,
'fields' => 'ids',
'date_query' => array( array( 'before' => '180 days ago' ) ),
) );
foreach ( $ids as $id ) {
wp_delete_post( $id, true ); // 第二个参数为 true 表示强制删除
}
} );
步骤4:登记自定义数据的导出器。 若表单数据存在自建表里,用 wp_privacy_personal_data_exporters 登记,这样客户提交导出请求时,数据会自动包含在导出文件中。
<?php
// 让自建表单表接入 WordPress 的个人数据导出
add_filter( 'wp_privacy_personal_data_exporters', function ( $exporters ) {
$exporters['mf-custom-form'] = array(
'exporter_friendly_name' => '自定义表单条目',
'callback' => 'mf_custom_form_exporter',
);
return $exporters;
} );
function mf_custom_form_exporter( $email_address, $page = 1 ) {
global $wpdb;
$items = array();
$rows = $wpdb->get_results( $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}mf_form_entries WHERE email = %s",
$email_address
) );
foreach ( $rows as $row ) {
$items[] = array(
'group_id' => 'mf-custom-form',
'group_label' => '自定义表单条目',
'item_id' => 'mf-entry-' . $row->id,
'data' => array(
array( 'name' => '姓名', 'value' => $row->name ),
array( 'name' => '电话', 'value' => $row->phone ),
array( 'name' => '提交时间', 'value' => $row->created_at ),
),
);
}
return array( 'data' => $items, 'done' => true );
}
步骤5:同步处理上传的文件。 数据库条目删了,上传目录里的文件还在,这是最常被漏掉的一环。删除条目时要一并清理对应附件。
# 找出 uploads 中疑似表单上传的目录并统计体积(确认后再删)
du -sh wp-content/uploads/*/ 2>/dev/null | sort -hr | head -10
步骤6:走一遍内置的导出与擦除流程。 用测试邮箱发起一次导出请求,确认生成的 JSON / HTML 文件里包含了表单数据;再发起一次擦除请求,确认条目被删除。
# 清理过期的个人数据导出文件(WordPress 自带计划任务会自动执行)
wp cron event list | grep -i privacy
wp cron event run wp_privacy_delete_old_export_files
步骤7:把通知邮件也纳入管理。 通知邮件里的个人信息同样属于个人数据。要么缩短邮件的保留期,要么把通知改成「只包含必要字段 + 后台查看链接」,减少数据扩散面。
步骤8:记录处理日志。 每次执行导出或擦除,留下时间、操作人、范围记录。合规检查时,这份日志就是证据。
常见踩坑
- 只删数据库不删文件。条目删了,
wp-content/uploads里的身份证照片还能通过 URL 直接访问,风险更大。 - 回收站没清空。
wp_delete_post()默认进回收站,数据依然存在,必须传第二个参数true强制删除;或者像Advanced Database Cleaner 清理冗余数据那样定期清理。 - 导出文件本身成了泄露源。导出链接通过邮件发送,链接在有效期内被转发就会泄露数据。WordPress 生成的导出文件会定期清理,别把它挪到公开目录。
- 备份里还留着已删除的数据。客户要求删除后,历史备份里依然存着旧数据。要在隐私政策里说明备份的保留周期,并确保备份加密存储。
- 擦除请求被忽略。管理员没及时处理后台的擦除请求,超期即构成违规。指定责任人并设提醒。
- 案例:某欧洲客户的 WordPress 站点收到数据删除请求,运营同学在后台删了表单插件里看到的条目就回复「已删除」。半年后对方做合规审计,发现
wp-content/uploads里仍可访问其上传的身份证明扫描件,且历史备份里也有完整记录,最终被要求出具整改说明。教训是:删除动作必须覆盖数据库、文件、备份三个层面,缺一不可。 - 留存周期没有写在任何地方。客户问「你们保存我多久的数据」,客服答不上来。写进隐私政策,并且真的按它执行。
- 多个表单插件数据分散。站点换了表单插件后,旧插件的数据表还留在数据库里无人管理,成了「影子数据仓库」。
总结
表单数据的合规可以拆成四件事:知道数据在哪(盘点)→ 规定存多久(留存策略)→ 到期自动删(清理任务)→ 客户要时能导出能删除(接入隐私工具)。其中最容易缺的是第二项和第四项:留存周期要么没定,要么定了不执行;隐私工具要么没用,要么没把自建表登记进去。把这几件事补齐,成本不高,但能避免最麻烦的那类问题。表单本身的字段与通知配置,可参考WPForms / Fluent Forms 拖拽表单配置教程与Contact Form 7 常见配置问题与扩展。
