WP DEVELOP

EP103. “Like 文章类型与教授页点赞数显示”

首页 WordPress 开发课程 LIKE / HEART 功能 · EP103
约 12 分钟· #EP103#LIKE / HEART 功能
🔒 登录后可标记已读

开始做「给教授点赞(Like/Heart)」功能:登录的 Subscriber 可以给教授点一次赞,再点一次取消,页面上公开显示该教授收到的总赞数。这一讲先完成静态骨架:教授详情页加一个心形图标+数字的赞组件;新建 like 自定义文章类型,每条 like 记录代表「某用户对某教授点了一次赞」(用文章作者代表点赞的人,配合一个自定义字段 liked_professor_id 存被点赞的教授 ID);然后用两个 WP_Query 分别查出「这个教授一共收到多少赞」和「当前用户是否已经点过赞」,让页面显示真实数据。跟 My Notes 不同,这个功能这一讲开始就决定不用 WordPress 内建 REST 端点,因为点赞涉及「一人一票」「校验目标真的是教授」这类自定义规则,作者更倾向于自己写端点、自己管权限。


涉及文件

  • wp-content/themes/fictional-university-theme/single-professor.php (修改)
  • wp-content/mu-plugins/university-post-types.php (修改,新增 like 文章类型)
  • 后台新建 ACF 字段组「Liked Professor ID」,数字类型,仅在 post type = like 时显示(后台操作,无对应代码文件)
  • 后台手动新建一条测试 Like 数据(后台操作,无对应代码文件)

代码实现

mu-plugins/university-post-types.php:新增 like 文章类型(复制 note 类型改造,去掉 REST 相关设置):

// wp-content/mu-plugins/university-post-types.php

// like post type
register_post_type('like', array(
  'supports' => array('title'),
  'public' => false,
  'show_ui' => true,
  'labels' => array(
    'name' => 'Likes',
    'add_new_item' => 'Add New Like',
    'edit_item' => 'Edit Like',
    'all_items' => 'All Likes',
    'singular_name' => 'Like'
  ),
  'menu_icon' => 'dashicons-heart'
));

single-professor.php:查询点赞数 + 当前用户是否已点赞,输出心形组件

<?php

  $likeCount = new WP_Query(array(
    'post_type' => 'like',
    'meta_query' => array(
      array(
        'key' => 'liked_professor_id',
        'compare' => '=',
        'value' => get_the_ID()
      )
    )
  ));

  $existStatus = 'no';

  $existQuery = new WP_Query(array(
    'author' => get_current_user_id(),
    'post_type' => 'like',
    'meta_query' => array(
      array(
        'key' => 'liked_professor_id',
        'compare' => '=',
        'value' => get_the_ID()
      )
    )
  ));

  if ($existQuery->found_posts) {
    $existStatus = 'yes';
  }

?>

<span class="like-box" data-exists="<?php echo $existStatus; ?>">
  <i class="fa fa-heart-o" aria-hidden="true"></i>
  <i class="fa fa-heart" aria-hidden="true"></i>
  <span class="like-count"><?php echo $likeCount->found_posts; ?></span>
</span>

关键改动点:

  • like 文章类型故意不设 show_in_rest(默认就是 false),也不设 capability_type/map_meta_cap——因为这个功能的权限规则(一人只能点一次、只能点教授不能点别的类型)比通用 CRUD 复杂,作者选择完全放弃 WordPress 内建 REST 端点,之后自己手写端点、自己在代码里检查权限,而不是套用现成机制再打补丁
  • 「谁点赞了谁」的数据模型:like 文章的作者代表点赞的用户,自定义字段 liked_professor_id(数字类型)存被点赞教授的文章 ID——一条 like 记录就是一对「用户 ID + 教授 ID」的组合,天然可以用 author + meta_query 组合查询
  • $likeCount:查询「有多少条 like 记录,liked_professor_id 等于当前教授的 ID」,不限定作者,得到的 found_posts 就是这位教授的总赞数
  • $existQuery:在 $likeCount 的查询条件基础上,多加一个 'author' => get_current_user_id(),只查「当前登录用户」对「当前教授」点的赞——如果 found_posts > 0,说明已经点过,把 $existStatus 设为 'yes'
  • found_posts 这个属性的好处是不受分页设置影响,即使 posts_per_page 设成 1 或 2,它依然会给出符合条件的总数,不用额外处理分页逻辑
  • 前台样式已经提前写好:.like-box 上的 data-exists 属性配合 CSS,data-exists="yes" 时心形图标会显示成实心(fa-heart),否则显示空心(fa-heart-o)——这一讲只负责让 PHP 算出正确的 yes/no 值填进这个属性,不需要碰 CSS

[截图:前台教授详情页的点赞组件(空心/实心心形图标 + 赞数)]


Hook / Function 速查

名称类型用途
$query->found_postsWP_Query 对象属性查询匹配到的总文章数,不受分页参数影响

常见坑

  • 忘记给 like 文章类型的 ACF 字段设置 required => 否——程序化创建 like 文章时会先创建文章、再补上自定义字段,短暂的中间状态下这个字段是空的,设成必填会导致创建流程报错
  • 忘记同时查「总赞数」和「当前用户是否已赞」这两个独立的查询,只查一个——两者的过滤条件不同(一个不限作者、一个限定当前作者),少了任何一个都拿不到完整的显示效果

延伸 / 后续讲座会用到

下一讲开始写自定义 REST API 端点和前端 JavaScript,让点击心形图标真正触发「创建/删除 like 记录」的请求。


Sources

Udemy:

  • Become a WordPress Developer: Unlocking Power With Code — Section 20, EP103