隐私政策、结算页、会员中心等关键页面可能被主题、插件或业务配置引用。保护它们不能靠在删除按钮点击后 exit:那会留下不完整响应,也无法覆盖批量操作、REST、WP-CLI 或其他代码路径。
先维护明确的受保护 ID
不同环境的文章 ID 可能不同。生产项目可把这些 ID 存进站点选项,或直接读取 WordPress/插件已有配置:
<?php
function site_get_protected_post_ids(): array {
$ids = array(
(int) get_option(
'wp_page_for_privacy_policy'
),
(int) get_option( 'page_on_front' ),
(int) get_option( 'woocommerce_cart_page_id' ),
(int) get_option( 'woocommerce_checkout_page_id' ),
(int) get_option( 'woocommerce_myaccount_page_id' ),
);
return array_values(
array_unique(
array_filter( $ids )
)
);
}
如果项目没有 WooCommerce,删除对应选项。不要把不存在的插件函数作为无条件依赖。
在权限层阻止删除
<?php
add_filter(
'map_meta_cap',
function (
array $caps,
string $cap,
int $user_id,
array $args
): array {
if (
! in_array(
$cap,
array( 'delete_post', 'delete_page' ),
true
)
) {
return $caps;
}
$post_id = isset( $args[0] )
? absint( $args[0] )
: 0;
if (
$post_id &&
in_array(
$post_id,
site_get_protected_post_ids(),
true
)
) {
return array( 'do_not_allow' );
}
return $caps;
},
10,
4
);
返回 do_not_allow 会让标准后台、REST 等遵守能力检查的入口拒绝操作,包括管理员。若超级管理员必须有紧急操作通道,应设计显式维护模式和审计记录,不要暗藏一个 URL 参数后门。
为直接调用增加短路保护
第三方代码可能直接调用删除函数而不先检查权限。可以再使用官方短路过滤器:
<?php
add_filter(
'pre_trash_post',
function ( $trash, WP_Post $post ) {
if (
in_array(
$post->ID,
site_get_protected_post_ids(),
true
)
) {
return false;
}
return $trash;
},
10,
2
);
add_filter(
'pre_delete_post',
function (
$delete,
WP_Post $post,
bool $force_delete
) {
if (
in_array(
$post->ID,
site_get_protected_post_ids(),
true
)
) {
return false;
}
return $delete;
},
10,
3
);
短路保护应该放在站点专用插件中,并配自动化测试。主题切换不能让关键数据突然失去保护。
保护不等于备份
- 页面仍可能被改成草稿、修改 slug、清空内容或移除模板。
- 选项可能指向另一个页面。
- 数据库管理员和服务器运维仍能直接删除数据。
- 代码错误也可能绕过正常 WordPress API。
因此还需要版本修订、数据库备份、暂存环境和恢复演练。真正重要的是“能够发现并恢复”,不是把后台按钮藏起来。