Возможно, я реализую ту же функцию в ближайшие 2 месяца. Я уже начал исследовать плагины, но, как говорится в вашем вопросе, это не так сложно.
Я пытаюсь вернуться тогда, но сначала мне нужна страница профиля внешнего интерфейса, где я могу перечислить избранное.
Первое впечатление пока выглядит хорошо, но сначала я бы уделил внимание массиву $_POST
, очистил и, возможно, проверил значения, потому что иногда не только ваш ajax будет вызывать.
if ( isset($_POST['userid']) && isset($_POST['favoriteid']) ) { // Both $_POST values exist
$userid = filter_var($_POST['userid'], FILTER_SANITIZE_NUMBER_INT);
$favoriteid = filter_var($_POST['favoriteid'], FILTER_SANITIZE_NUMBER_INT);
if ( filter_var($userid, FILTER_VALIDATE_INT) && filter_var($favoriteid, FILTER_VALIDATE_INT) ) {
// $_POST was save, both values are Integers
}
}
второй относится к get_field
, который является функцией, предоставляемой плагином ACF. поэтому при деактивации или замене на JCF это может привести к ошибкам.
Этого можно избежать, используя if ( function_exists('get_field') ) {
. Тогда ваш код перестает работать только тогда, когда ACF деактивируется.
В противном случае использование функции ACF кажется необязательным, и вместо него можно использовать собственную функцию WP get_user_meta :
function is_favorite($userid, $favoriteid){
$favorites_list = get_user_meta($userid, 'favorites_list', true);
// check the new output instead of get_field
return in_array( $favoriteid, $favorites_list );
}
а также все звонки на get_field('favorites', 'user_' .$favoriteid)
кажутся неправильными. Документы ACF говорят, что вторым параметром get_field
является идентификатор сообщения, так что я не знаю, что значит user_. Я бы позвонил:
function get_favorites_num($favoriteid){
return get_user_meta($favoriteid, 'favorites', true) || 0;
}
Теперь у меня есть своя собственная любимая система, в которой пользователи могут добавлять избранные сообщения из определенного c post_type
HTML
<?php while ( have_posts() ) : the_post() ?>
<?php
$customPostsMeta = get_post_custom();
$favorite_class = 'favorite-me disabled';
$fav_count = isset($customPostsMeta['_favorites']) ? intval($customPostsMeta['_favorites'][0]) : 0;
$fav_count_text = $fav_count > 0 ? '(' . $fav_count . ')' : '';
$fav_count = ' <span class="fav-count clearfix">' . $fav_count_text . '</span>';
$favorite_title = '';
if ( is_user_logged_in() ) {
$user = wp_get_current_user();
$favorites = get_user_meta($user->ID, '_favorite_posts', true);
$fav_key = array_search($post_id, $favorites);
$is_favorite = ( $fav_key !== false );
if ( $is_favorite ) {
$favorite_class .= ' is-favorite';
$favorite_title = ' title="' . get_the_title() . ' ' . __('favorisieren', 'myTheme') . '"';
} else {
$favorite_title = ' title="' . get_the_title() . ' ' . __('nicht mehr favorisieren', 'myTheme') . '"';
}
}
?>
<a class="<?php echo $favorite_class; ?>" href="#post-<?php the_ID() ?>"<?php echo $favorite_title; ?>><?php echo __('Favorit', 'myTheme')?><?php echo $fav_count; ?></a>
<?php endwhile; ?>
JS
// i use a small self written JS module frame where this is included as module
// favorite.setup() is fired imediatly, favorite.ready() fires on document ready
// you can see a full version here: https://dev.alphabetisierung.at/wp-content/themes/sandbox_2017/js/actions.js
// line 732
/**
* Favorites ajax system
* =====================
* https://stackoverflow.com/questions/60468237
*/
favorite: {
options: {
selectors: {
link: '.favorite-me',
fav_count: '.fav-count'
},
classNames: {
disabled: 'disabled',
is_favorite: 'is-favorite',
}
},
events: function(){
var options = this.options,
selectors = options.selectors,
classNames = options.classNames,
info = this.info;
this.$favorites.on('click', function(event){
var post_id = this.hash.replace('#post-', ''),
$favorite_link = $(this).addClass(classNames.disabled),
$fav_count = $favorite_link.children(selectors.fav_count),
$favorite = $.ajax({
url: myTheme.page.urls.ajax,
type: 'post',
data: {
action: info.name, // derived from the module name "favorite"
verify: myTheme.page.verify, // https://developer.wordpress.org/reference/functions/check_ajax_referer/
post_id: post_id
// user_id of user who takes the action is not necessary
}
});
$favorite.done(function(data){
var fav_count = data.hasOwnProperty('fav_count') ? parseInt(data.fav_count) : 0,
fav_count_text = '',
is_favorite = data.hasOwnProperty('is_favorite') ? data.is_favorite : false;
if ( fav_count > 0 ) {
fav_count_text = '(' + fav_count + ')';
}
$fav_count.html(fav_count_text);
if ( is_favorite && !$favorite_link.is('.' + classNames.is_favorite) ) {
$favorite_link.addClass(classNames.is_favorite);
} else {
$favorite_link.removeClass(classNames.is_favorite);
}
$favorite_link.removeClass(classNames.disabled);
});
event.preventDefault();
});
},
ready: function ready(){
var selectors = this.options.selectors,
classNames = this.options.classNames;
this.$favorites = $(selectors.link).removeClass(classNames.disabled);
this.events();
},
setup: function setup(){
var setup = myTheme.info.is_user_logged_in && myTheme.info.post_type === 'my_custom_post_type';
return setup; // only for my post_type
}
PHP
add_action('wp_enqueue_scripts', 'myTheme_enqueue_scripts');
add_action('wp_ajax_favorite', 'myTheme_set_favorite');
// wp_ajax_nopriv_{action} is not necessary when feature is only for logged in users
function myTheme_enqueue_scripts(){
$data = array(
'id' => get_the_ID(),
'urls' => array(
'ajax' => admin_url('admin-ajax.php'),
'template' => get_stylesheet_directory_uri(),
),
'verify' => wp_create_nonce('myThemeOrAction_ajax_call'), // used for check_ajax_referer()
// ...
'info' => array(
// ...
'is_user_logged_in' => is_user_logged_in(),
'post_type' => get_post_type(),
),
);
// ...
wp_localize_script('actions', 'myTheme_data', $data );
}
function myTheme_set_favorite(){
check_ajax_referer('myThemeOrAction_ajax_call', 'verify');
if ( isset($_POST['post_id']) ) {
$user = wp_get_current_user(); // here we get the user ID of the current user
$post_id = filter_var($_POST['post_id'], FILTER_SANITIZE_NUMBER_INT);
$post = get_post($post_id);
// $fav_id = filter_var($_POST['fav_id'], FILTER_SANITIZE_NUMBER_INT);
// $fav_user = get_userdata($fav_id); // WP_User
$is_favorite = false;
if ( $post instanceof WP_Post ) { // post ID is valid
// for user favorites it would be
// if ( $fav_user instanceof WP_User ) {
$fav_count = intval(get_post_meta($post->ID, '_favorites', true));
$favorites = get_user_meta($user->ID, '_favorite_posts', true);
if ( !filter_var($fav_count, FILTER_VALIDATE_INT) ) {
$fav_count = 0;
}
if ( !is_array($favorites) || empty($favorites) ) {
$favorites = array();
}
$fav_key = array_search($post->ID, $favorites);
if ( $fav_key !== false ) { // is favorite, remove it
$fav_count--;
unset($favorites[$fav_key]);
} else { // is no favorite, add it
$fav_count++;
$favorites[] = $post->ID;
$is_favorite = true;
}
// set favorite counter
update_post_meta($post->ID, '_favorites', $fav_count);
// set favorite list
update_user_meta($user->ID, '_favorite_posts', $favorites);
// Output
$json = array(
'fav_count' => $fav_count,
'favorites' => $favorites,
'error' => false,
'is_favorite' => $is_favorite,
);
} else {
$json = array('is_favorite' => $is_favorite, 'error' => true, 'message' => 'Invalid Post ID');
}
} else {
$json = array('is_favorite' => $is_favorite, 'error' => true, 'message' => 'No post_id Post ID sent');
}
// wp_send_json sets the http header and ends the request
wp_send_json($json);
}
это то, что я заметил на способ:
- проверить реферер с помощью
wp_create_nonce()
и check_ajax_referer()
- check JSON ключи данных результата для существования с
data.hasOwnProperty('key')
, чтобы избежать возможных JS ошибок - проверить действительный
WP_User
или WP_Post
объект - идентификатор текущего пользователя с не нужно отправлять с POST
wp_ajax_nopriv_{action}
не требуется, когда функция только для входа в систему пользователи - используйте
wp_send_json()
для окончания ответа
С уважением Том