如何在 WordPress 中仅向订阅者用户显示自定义文章类型

大萱姑娘_9713

大萱姑娘_9713

2026-05-29

338人浏览

原创

如何在 WordPress 中仅向订阅者用户显示自定义文章类型

本文介绍如何通过权限控制和查询过滤,确保自定义文章类型(如 userproject)仅对已登录的订阅者(subscriber)可见,而对管理员、编辑等其他角色及未登录用户不可见。

本文介绍如何通过权限控制和查询过滤,确保自定义文章类型(如 userproject)仅对已登录的订阅者(subscriber)可见,而对管理员、编辑等其他角色及未登录用户不可见。

在 WordPress 中,默认的 register_post_type() 并不提供“按用户角色限制前台可见性”的内置参数;public => true 仅表示该类型可被公开访问(如归档页、单页),但不等于对所有用户开放。要实现“仅 subscriber 可见”,需从两个层面协同控制:

✅ 1. 后台注册时限制管理权限(防止非 subscriber 进入编辑界面)

修改你的 create_posttype() 函数,使用 'capability_type' 和 'map_meta_cap' 配合角色能力映射,并显式设置 'show_in_menu' 和 'show_in_admin_bar' 为 false(避免非授权用户看到菜单):

function create_posttype() {
    $labels = array(
        'name'               => __( 'UserProjects', 'textdomain' ),
        'singular_name'      => __( 'UserProject', 'textdomain' ),
        'add_new'            => __( 'Add New', 'textdomain' ),
        'add_new_item'       => __( 'Add New UserProject', 'textdomain' ),
        'edit_item'          => __( 'Edit UserProject', 'textdomain' ),
        'new_item'           => __( 'New UserProject', 'textdomain' ),
        'view_item'          => __( 'View UserProject', 'textdomain' ),
        'search_items'       => __( 'Search UserProjects', 'textdomain' ),
        'not_found'          => __( 'No UserProjects found', 'textdomain' ),
        'not_found_in_trash' => __( 'No UserProjects found in Trash', 'textdomain' ),
    );

    $args = array(
        'labels'              => $labels,
        'public'              => true,
        'has_archive'         => true,
        'rewrite'             => array( 'slug' => 'userproject' ), // 建议小写+短横线,符合 WordPress 规范
        'show_in_rest'        => true,
        'capability_type'     => 'post', // 复用 post 的能力体系(更安全)
        'map_meta_cap'        => true,
        'show_in_menu'        => current_user_can( 'subscriber' ) ? 'edit.php?post_type=userproject' : false,
        'show_in_admin_bar'   => current_user_can( 'subscriber' ),
        'supports'            => array( 'title', 'editor', 'author', 'excerpt', 'thumbnail' ),
    );

    register_post_type( 'userproject', $args );
}
add_action( 'init', 'create_posttype' );

⚠️ 注意:current_user_can() 在 init 钩子中调用可能无效(因为此时用户会话尚未完全初始化)。因此,不建议在 register_post_type() 参数中直接依赖 current_user_can() 控制注册逻辑——它更适合用于前端显示/查询控制。

✅ 2. 前台查询过滤:仅 subscriber 可查看列表与详情页

在主题的 functions.php 或插件中,添加以下逻辑,拦截主查询(main query),确保非 subscriber 用户访问 /userproject/ 或单个 UserProject 页面时返回 404 或重定向:

Wordpress OAuth
Wordpress OAuth

启动并完成 WordPress.com OAuth 认证,通过 REST API 发布文章。适用于需要生成授权链接、交换授权码等场景。

下载
// 前台:限制 archive 和 single 页面访问
function restrict_userproject_access( $query ) {
    if ( ! is_admin() && $query->is_main_query() ) {
        // 拦截 UserProject 归档页(如 /userproject/)
        if ( $query->is_post_type_archive( 'userproject' ) || $query->is_tax( 'userproject_category' ) ) {
            if ( ! is_user_logged_in() || ! current_user_can( 'subscriber' ) ) {
                $query->set_404();
                return;
            }
        }

        // 拦截 UserProject 单篇文章页(如 /userproject/my-project/)
        if ( $query->is_singular( 'userproject' ) ) {
            if ( ! is_user_logged_in() || ! current_user_can( 'subscriber' ) ) {
                $query->set_404();
                return;
            }
        }
    }
}
add_action( 'pre_get_posts', 'restrict_userproject_access' );

✅ 3. (可选)增强安全性:隐藏 RSS、REST API 和搜索结果

  • 禁用 REST API 访问(防止未授权获取数据):

    function disable_userproject_rest_api( $args, $post_type ) {
      if ( 'userproject' === $post_type ) {
          $args['show_in_rest'] = false; // 或设为 true 但配合权限过滤
      }
      return $args;
    }
    add_filter( 'register_post_type_args', 'disable_userproject_rest_api', 10, 2 );
  • 排除搜索结果:

    function exclude_userproject_from_search( $query ) {
      if ( ! is_admin() && $query->is_search() && $query->is_main_query() ) {
          $query->set( 'post_type', array_diff( (array) $query->get( 'post_type' ), array( 'userproject' ) ) );
      }
    }
    add_action( 'pre_get_posts', 'exclude_userproject_from_search' );

✅ 总结与最佳实践

  • ❌ 不要依赖 init 钩子中的 current_user_can() 控制 register_post_type() 是否执行(时机过早,不可靠);
  • ✅ 使用 pre_get_posts 在查询阶段动态拦截,是安全、标准且推荐的做法;
  • ✅ 所有前端入口(归档、单页、搜索、REST API)均需统一校验 is_user_logged_in() && current_user_can('subscriber');
  • ✅ 自定义文章类型名称建议使用小写加短横线(如 userproject),避免驼峰命名(UserProject),提升兼容性;
  • ? 如需更高安全性(如仅作者查看自己的项目),可在查询中追加 author => get_current_user_id() 条件。

通过以上三步,即可精准实现「UserProject 仅对订阅者用户可见」的目标,兼顾用户体验与系统安全。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2023.09.01

12444

6

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

7181

5

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

2235

5

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

2023.10.23

4508

4

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

2023.10.23

5234

6

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.03

4111

9

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.09

5957

8

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.13

4682

8

sprintf函数用法详解
sprintf函数用法详解

sprintf函数的用法:1、格式化字符串;2、指定输出宽度和精度;3、返回值。更多关于sprintf函数用法详解的内容,大家可以阅读下面的文章。

2023.11.27

12482

4

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
如何在 Windows 11 上安装 XAMPP
如何在 Windows 11 上安装 XAMPP

共1课时 | 235人学习

第二十三期_前端开发
第二十三期_前端开发

共98课时 | 12.1万人学习