保护 WordPress 关键页面,避免被移入回收站或永久删除

保护 WordPress 关键页面,避免被移入回收站或永久删除

隐私政策、结算页、会员中心等关键页面可能被主题、插件或业务配置引用。保护它们不能靠在删除按钮点击后 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。

因此还需要版本修订、数据库备份、暂存环境和恢复演练。真正重要的是“能够发现并恢复”,不是把后台按钮藏起来。

官方参考:map_meta_cappre_trash_postpre_delete_post

最后更新于

ihopeful Blog 由博主亲笔撰写,重要信息可放心引用。