Задать вопрос
@Kypidon4ik
Фрилансер, Wordpress developer

Почему атомарная операция не отрабатывает(счетчик стопортиться на 1)?

<?php
/**
 * Получает количество просмотров поста
 * 
 * @param int $post_id ID поста
 * @return int Количество просмотров
 */
function gt_get_post_view($post_id) {
  
    $views = (int)get_post_meta($post_id, 'post_views_count', true);
    
    return $views;
}

/**
 * Увеличивает счетчик просмотров поста
 * 
 * @param int $post_id ID поста
 * @return bool|int Новое количество просмотров или false при ошибке
 */
function gt_set_post_view($post_id) {
    $post_id = absint($post_id);
    
    // Проверяем существование поста
    if (!get_post($post_id)) {
        return false;
    }
    
    global $wpdb;
    
    // Атомарное увеличение через SQL
    $result = $wpdb->query($wpdb->prepare("
        INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) 
        VALUES (%d, 'post_views_count', '1') 
        ON DUPLICATE KEY UPDATE meta_value = CAST(meta_value AS UNSIGNED) + 1
    ", $post_id));
    
    if ($result !== false) {
        // Получаем обновленное значение
        return (int)get_post_meta($post_id, 'post_views_count', true);
    }
    
    return false;
}

/**
 * Добавляет колонку просмотров в админ-панели
 * 
 * @param array $columns Существующие колонки
 * @return array Модифицированные колонки
 */
function gt_posts_column_views($columns) {
    // Вставляем колонку просмотров после колонки заголовка
    $new_columns = array();
    
    foreach ($columns as $key => $value) {
        $new_columns[$key] = $value;
        if ($key === 'title') {
            $new_columns['post_views'] = 'Views';
        }
    }
    
    return $new_columns;
}

/**
 * Выводит количество просмотров в колонке админ-панели
 * 
 * @param string $column Название колонки
 */
function gt_posts_custom_column_views($column) {
    if ($column !== 'post_views') {
        return;
    }
    $id = get_the_ID();
    $user = wp_get_current_user();
    $allowed_roles = array('administrator', 'advertisers', 'web_editor');
    
    if (array_intersect($allowed_roles, $user->roles)) {
        $views = gt_get_post_view($id);
        echo '<strong>' . number_format_i18n($views) . '</strong>';
    } else {
        echo '<span style="color:#ccc;">No access</span>';
    }
}

/**
 * Возвращает HTML с количеством просмотров для вставки в контент
 * 
 * @param int $post_id ID поста
 * @return string HTML с количеством просмотров или пустая строка
 */
function gt_in_post_view($post_id = null) {
    // Если ID поста не передан, используем текущий
    if (null === $post_id) {
        $post_id = get_the_ID();
    }
    
    $post_id = absint($post_id);
    $user = wp_get_current_user();
    $allowed_roles = array('administrator', 'advertisers');
    
    if (array_intersect($allowed_roles, $user->roles)) {
        $views = gt_get_post_view($post_id);
        
        return sprintf(
            '<div class="post-views-wrapper">
                <span class="post-views-count">%s: <strong>%s</strong></span>
            </div>',
            'Views count',
            number_format_i18n($views)
        );
    }
    
    return '';
}

/**
 * Делаем колонку сортируемой
 */
function gt_sortable_views_column($columns) {
    $columns['post_views'] = 'post_views'; 
    return $columns;
}
add_filter('manage_edit-post_sortable_columns', 'gt_sortable_views_column');

/**
 * Обработка сортировки по колонке просмотров
 */
function gt_views_column_orderby($query) {
    if (!is_admin() || !$query->is_main_query()) {
        return;
    }
    
    if ($query->get('orderby') === 'post_views') {
        $query->set('meta_key', 'post_views_count');
        $query->set('orderby', 'meta_value_num');
    }
}
add_action('pre_get_posts', 'gt_views_column_orderby');

// Добавляем колонки в админ-панель
add_filter('manage_posts_columns', 'gt_posts_column_views');
add_action('manage_posts_custom_column', 'gt_posts_custom_column_views', 10, 2);


Версия WP 6.8.3, есть объектный кеш redis + wp faster cache
  • Вопрос задан
  • 54 просмотра
Подписаться 1 Простой 3 комментария
Пригласить эксперта
Ответы на вопрос 1
wppanda5
@wppanda5 Куратор тега WordPress
WordPress Mедведь
При выполнении вашего INSERT никакого дубликата не возникает, (post_id, meta_key) не имеют уникального индекса и ON DUPLICATE KEY UPDATE не срабатывает.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы