Ikhtisar Chapter 19: Like / Heart Count
Apa yang Dipelajari?
Membangun fitur like/unlike pada halaman professor — termasuk custom post type, custom REST API endpoint, validasi ketat, dan real-time UI toggle.
Poin Utama
1. Arsitektur Data
- CPT
likemenyimpan setiap like sebagai post terpisah - ACF field
liked_professor_id(tipe Number) di setiap like → menyimpan ID professor yang di-like public => false, tanpashow_in_rest(karena tidak pakai REST API default)
2. Menampilkan Like Count & Status
Menggunakan WP_Query + meta_query di single-professor.php:
| Query | Tujuan |
|---|---|
$likeCount | Hitung total like untuk professor ini (found_posts) |
$existQuery | Cek apakah user saat ini sudah like (filter author + meta_query) |
HTML like box menyimpan data di atribut: data-exists, data-professor, data-like.
3. Custom REST API Endpoint (Bukan Default)
Dua route dengan URL sama tapi method berbeda:
| Method | URL | Callback |
|---|---|---|
| POST | /university/v1/manageLike | createLike() |
| DELETE | /university/v1/manageLike | deleteLike() |
Alasannya: butuh custom logic yang tidak tersedia di REST API default (limit 1 like, validasi post type).
4. Server-Side Validasi di createLike()
| Check | Alasan |
|---|---|
is_user_logged_in() | Hanya user login yang boleh like |
$existQuery->found_posts == 0 | User belum pernah like professor ini |
get_post_type($professor) == 'professor' | ID yang dikirim benar-benar professor (bukan post/page lain) |
sanitize_text_field() | Sanitasi input dari client |
Like dibuat dengan wp_insert_post() + meta_input untuk set ACF field secara programmatic.
5. Server-Side Validasi di deleteLike()
- Cek
get_current_user_id() == get_post_field('post_author', $likeId)→ hanya bisa hapus like sendiri - Cek
get_post_type($likeId) == 'like'→ mencegah penghapusan post type lain wp_delete_post($id, true)→ hapus permanen (skip trash)
6. Real-Time UI Update (JavaScript)
- Create: toggle
data-exists→"yes", increment angka, simpan ID like baru didata-like - Delete: toggle
data-exists→"no", decrement angka, kosongkandata-like - Gunakan
.attr()(bukan.data()) untuk baca atribut terbaru dari DOM parseInt(string, 10)untuk konversi string ke angka sebelum increment/decrement
7. Dispatcher Pattern
ourClickDispatcher() membaca data-exists lalu memanggil createLike() atau deleteLike() — satu event handler, dua aksi.
Satu Kalimat
Fitur Like dibangun dengan custom endpoint (bukan REST API default) karena membutuhkan validasi khusus: satu like per user per professor, verifikasi post type, dan ownership check saat delete.