EP103. “Like 文章类型与教授页点赞数显示”
🔒 登录后可标记已读开始做「给教授点赞(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_posts | WP_Query 对象属性 | 查询匹配到的总文章数,不受分页参数影响 |
常见坑
- 忘记给
like文章类型的 ACF 字段设置required => 否——程序化创建 like 文章时会先创建文章、再补上自定义字段,短暂的中间状态下这个字段是空的,设成必填会导致创建流程报错 - 忘记同时查「总赞数」和「当前用户是否已赞」这两个独立的查询,只查一个——两者的过滤条件不同(一个不限作者、一个限定当前作者),少了任何一个都拿不到完整的显示效果
延伸 / 后续讲座会用到
下一讲开始写自定义 REST API 端点和前端 JavaScript,让点击心形图标真正触发「创建/删除 like 记录」的请求。
Sources
Udemy:
- Become a WordPress Developer: Unlocking Power With Code — Section 20, EP103