You can use a button on the front and save the ID of the currently displayed post in user's meta. Here's a simple way to do this:
Output a Button on Front
You need to create a button in your single.php
( or whatever page you want ) to allow the user to actually set the post as a favorite. The below template does this. The like-overlay
class is used to create a loading effect while the request is being processed.
<div id="like-button" class="like btn btn-default" type="button">
<span class="fa fa-heart"></span>
<span class="like-overlay"><i class="fa fa-spin fa-circle-o-notch"></i></span>
</div>
<input type="hidden" value="<?php the_ID(); ?>" id="current-post-id"/>
<input type="hidden" value="<?php echo get_current_user_id(); ?>" id="current-user-id"/>
Add a Click event to the Button
When the user clicks the button, send an AJAX request to the server, and update the button based on the results. You might need to localize the script to pass the rest URL and other data.
$('#like-button').on('click',function (e) {
e.preventDefault();
$.ajax({
type: 'GET',
url: 'http://example.com/wp-json/my_route/v1/ajax_favorite',
data: { post_id: $('#current-post-id').val(), user_id : $('#current-user-id').val() },
beforeSend: function() {
$('#like-button').addClass('active').prop('disabled', true);
},
success: function(data){
$('#like-button').removeClass('active').prop('disabled', false);
if( data != null ){
if( data == '400' ) {
$('#like-button').removeClass('selected');
} else if( data == '200') {
$('#like-button').addClass('selected');
}
}
},
error:function(){
}
});
});
Process the Ajax Request Using REST-API
Now create a rest route and process the data. If the received post ID doesn't exists in the user meta, add it and return a successful code. If it does, remove it and let your script know about it.
add_action( 'rest_api_init', 'my_rest_routes');
function my_rest_routes() {
// Path to ajax like function
register_rest_route(
'my_route/v1',
'/ajax_favorite/',
array(
'methods' => 'GET',
'callback' => 'ajax_favorite'
)
);
}
function ajax_favorite(){
// If the ID is not set, return
if(!isset($_GET['post_id']) || !isset($_GET['user_id'])){
return $data['status'] = '500';
}
// Store user and product's ID
$post_id = sanitize_text_field($_GET['post_id']);
$user_id = sanitize_text_field($_GET['user_id']);
$user_meta = get_user_meta($user_id,'_favorite_posts',false);
// Check if the post is favorited or not
if( in_array( $post_id, $user_meta ) ){
delete_user_meta($user_id,'_favorite_posts',$post_id);
return $data['status'] = '400';
} else {
add_user_meta($user_id,'_favorite_posts',$post_id);
return $data['status'] = '200';
}
}
You can use this as a template to output any button that saves data from front-end to database. Don't forget to sanitize the data, and use nonce too.
Now of course all you need is to get the _favorite_posts
user meta whenever you want to display it.