В этом видео мы рассмотрим, как можно легко вставить код или даже целый плагин в блочную тему WordPress. Это особенно полезно для для новичков, которым сложно работать с файлами темы. Используем специальный плагин для вставки других плагинов.
Видео урок
/*
Plugin Name: Post Views Counter
Description: Простой и надежный плагин для подсчета просмотров записей и страниц
Version: 1.0
Author: Your Name
*/
// Предотвращение прямого доступа к файлу
if (!defined('ABSPATH')) {
exit;
}
// Создание таблицы в базе данных при активации плагина
register_activation_hook(FILE, 'pvc_create_table');
function pvc_create_table()
{
global $wpdb;
$table_name = $wpdb->prefix . 'post_views';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $table_name ( id mediumint(9) NOT NULL AUTO_INCREMENT, post_id mediumint(9) NOT NULL, view_count mediumint(9) DEFAULT 1 NOT NULL, last_viewed datetime DEFAULT CURRENT_TIMESTAMP NOT NULL, PRIMARY KEY (id), UNIQUE KEY post_id (post_id), KEY last_viewed (last_viewed) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql);
}
// Основная функция отслеживания просмотров
function pvc_track_view()
{
// Защита от множественных вызовов
static $tracked_posts = array();
// Пропускаем админку и AJAX запросы if (is_admin() || wp_doing_ajax()) { return; } global $post; if (!$post || !$post->ID) { return; } // Отслеживаем только записи и страницы if (!is_single() && !is_page()) { return; } $post_id = $post->ID; // Проверяем, не отслеживали ли мы уже этот пост в этом запросе if (in_array($post_id, $tracked_posts)) { return; } // Добавляем в список отслеженных $tracked_posts[] = $post_id; global $wpdb; $table_name = $wpdb->prefix . 'post_views'; // Проверяем существование таблицы $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name; if (!$table_exists) { pvc_create_table(); return; } // Проверяем, есть ли уже запись для этого поста $existing = $wpdb->get_row($wpdb->prepare("SELECT view_count FROM $table_name WHERE post_id = %d", $post_id)); if ($existing) { // Обновляем счетчик $wpdb->update( $table_name, array( 'view_count' => $existing->view_count + 1, 'last_viewed' => current_time('mysql') ), array('post_id' => $post_id), array('%d', '%s'), array('%d') ); } else { // Создаем новую запись $wpdb->insert( $table_name, array( 'post_id' => $post_id, 'view_count' => 1, 'last_viewed' => current_time('mysql') ), array('%d', '%d', '%s') ); }
}
// Добавляем отслеживание только на один хук
add_action('wp', 'pvc_track_view');
// Дополнительное отслеживание через JavaScript (только для кэшированных страниц)
function pvc_add_js_tracking()
{
// Отключаем JavaScript отслеживание - используем только PHP
return;
if (is_admin() || (!is_single() && !is_page())) { return; } global $post; if (!$post || !$post->ID) { return; } $post_id = $post->ID; $nonce = wp_create_nonce('pvc_js_track'); ?> <script type="text/javascript"> (function() { function pvcTrackView() { fetch('<?php echo admin_url('admin-ajax.php'); ?>', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: 'action=pvc_js_track&post_id=<?php echo $post_id; ?>&nonce=<?php echo $nonce; ?>' }).catch(function() { // Тихо игнорируем ошибки }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', pvcTrackView); } else { pvcTrackView(); } })(); </script> <?php
}
add_action('wp_footer', 'pvc_add_js_tracking');
// AJAX обработчик
function pvc_ajax_track()
{
if (!wp_verify_nonce($_POST['nonce'], 'pvc_js_track')) {
wp_die();
}
$post_id = intval($_POST['post_id']); if (!$post_id) { wp_die(); } global $wpdb; $table_name = $wpdb->prefix . 'post_views'; $existing = $wpdb->get_row($wpdb->prepare("SELECT view_count FROM $table_name WHERE post_id = %d", $post_id)); if ($existing) { $wpdb->update( $table_name, array( 'view_count' => $existing->view_count + 1, 'last_viewed' => current_time('mysql') ), array('post_id' => $post_id), array('%d', '%s'), array('%d') ); } else { $wpdb->insert( $table_name, array( 'post_id' => $post_id, 'view_count' => 1, 'last_viewed' => current_time('mysql') ), array('%d', '%d', '%s') ); } wp_die();
}
add_action('wp_ajax_pvc_js_track', 'pvc_ajax_track');
add_action('wp_ajax_nopriv_pvc_js_track', 'pvc_ajax_track');
// Функция получения просмотров
function pvc_get_post_views($post_id = null)
{
if (!$post_id) {
global $post;
if (!$post || !$post->ID) return 0;
$post_id = $post->ID;
}
global $wpdb; $table_name = $wpdb->prefix . 'post_views'; $views = $wpdb->get_var($wpdb->prepare("SELECT view_count FROM $table_name WHERE post_id = %d", $post_id)); return $views ? intval($views) : 0;
}
// Шорткод для отображения просмотров
function pvc_shortcode($atts)
{
$atts = shortcode_atts(array(
'post_id' => null,
'text' => 'Просмотров: '
), $atts);
$views = pvc_get_post_views($atts['post_id']); return $atts['text'] . number_format($views);
}
add_shortcode('post_views', 'pvc_shortcode');
// Шорткод для отображения таблицы популярных записей
function pvc_popular_posts_shortcode($atts)
{
$atts = shortcode_atts(array(
'limit' => 10,
'show_views' => 'true',
'show_date' => 'false',
'title' => 'Популярные записи',
'post_type' => 'post'
), $atts);
global $wpdb; $table_name = $wpdb->prefix . 'post_views'; $limit = intval($atts['limit']); $post_type = sanitize_text_field($atts['post_type']); $posts = $wpdb->get_results($wpdb->prepare(" SELECT p.ID, p.post_title, p.post_date, pv.view_count FROM $table_name pv INNER JOIN {$wpdb->posts} p ON pv.post_id = p.ID WHERE p.post_status = 'publish' AND p.post_type = %s ORDER BY pv.view_count DESC LIMIT %d ", $post_type, $limit)); if (empty($posts)) { return '<p>Пока нет данных о просмотрах.</p>'; } $output = '<div class="pvc-popular-posts">'; if (!empty($atts['title'])) { $output .= '<h3>' . esc_html($atts['title']) . '</h3>'; } $output .= '<ol class="pvc-posts-list">'; foreach ($posts as $post_item) { $output .= '<li class="pvc-post-item">'; $output .= '<a href="' . get_permalink($post_item->ID) . '">' . esc_html($post_item->post_title) . '</a>'; if ($atts['show_views'] === 'true') { $output .= ' <span class="pvc-views">(' . number_format($post_item->view_count) . ' просмотров)</span>'; } if ($atts['show_date'] === 'true') { $output .= ' <span class="pvc-date">' . date('d.m.Y', strtotime($post_item->post_date)) . '</span>'; } $output .= '</li>'; } $output .= '</ol></div>'; return $output;
}
add_shortcode('popular_posts', 'pvc_popular_posts_shortcode');
// Функция для получения популярных записей (для использования в темах)
function pvc_get_popular_posts($limit = 10, $post_type = 'post')
{
global $wpdb;
$table_name = $wpdb->prefix . 'post_views';
return $wpdb->get_results($wpdb->prepare(" SELECT p.ID, p.post_title, p.post_date, pv.view_count FROM $table_name pv INNER JOIN {$wpdb->posts} p ON pv.post_id = p.ID WHERE p.post_status = 'publish' AND p.post_type = %s ORDER BY pv.view_count DESC LIMIT %d ", $post_type, intval($limit)));
}
// Добавление страницы в админ-панель
function pvc_add_admin_menu()
{
add_menu_page(
'Просмотры записей',
'Просмотры',
'manage_options',
'post-views',
'pvc_admin_page',
'dashicons-chart-bar',
25
);
}
add_action('admin_menu', 'pvc_add_admin_menu');
// Страница админки
function pvc_admin_page()
{
global $wpdb;
$table_name = $wpdb->prefix . 'post_views';
// Проверка существования таблицы $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name; if (!$table_exists) { pvc_create_table(); echo '<div class="notice notice-info"><p>Таблица была создана.</p></div>'; $table_exists = true; } // Получаем статистику $total_records = $wpdb->get_var("SELECT COUNT(*) FROM $table_name"); $total_views = $wpdb->get_var("SELECT SUM(view_count) FROM $table_name"); // Популярные записи $popular_posts = $wpdb->get_results(" SELECT p.post_title, pv.view_count, pv.last_viewed, p.ID, p.post_type FROM $table_name pv LEFT JOIN {$wpdb->posts} p ON pv.post_id = p.ID ORDER BY pv.view_count DESC LIMIT 50 "); ?> <div class="wrap"> <h1>📊 Статистика просмотров</h1> <!-- Общая статистика --> <div class="pvc-stats-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin: 20px 0;"> <div style="background: #fff; border: 1px solid #ccd0d4; border-radius: 4px; padding: 20px; text-align: center;"> <h3 style="margin: 0 0 10px 0; color: #1d2327;">Всего записей</h3> <div style="font-size: 2em; font-weight: bold; color: #2271b1;"><?php echo number_format($total_records); ?></div> </div> <div style="background: #fff; border: 1px solid #ccd0d4; border-radius: 4px; padding: 20px; text-align: center;"> <h3 style="margin: 0 0 10px 0; color: #1d2327;">Всего просмотров</h3> <div style="font-size: 2em; font-weight: bold; color: #d63638;"><?php echo number_format($total_views); ?></div> </div> </div> <!-- Инструкции по использованию --> <div style="background: #f0f6fc; border: 1px solid #c3dbf7; border-radius: 4px; padding: 20px; margin: 20px 0;"> <h3>💡 Как использовать плагин:</h3> <h4>Шорткоды:</h4> <ul> <li>[post_views] - показать количество просмотров текущей записи</li> <li>[post_views post_id="123"] - показать просмотры конкретной записи</li> <li>[post_views text="Читали: "] - изменить текст перед числом</li> <li>[popular_posts] - показать список из 10 популярных записей</li> <li>[popular_posts limit="5" show_views="true" show_date="true"] - настроить отображение</li> </ul> <h4>В PHP коде темы:</h4> <ul> <li>echo pvc_get_post_views(); - получить число просмотров</li> <li>$popular = pvc_get_popular_posts(5); - получить массив популярных записей</li> </ul> </div> <?php if (!empty($popular_posts)): ?> <h2>🏆 Популярные записи</h2> <table class="wp-list-table widefat fixed striped"> <thead> <tr> <th style="width: 60px;">#</th> <th>Название записи</th> <th style="width: 80px;">Тип</th> <th style="width: 100px;">Просмотры</th> <th style="width: 150px;">Последний просмотр</th> <th style="width: 80px;">Действия</th> </tr> </thead> <tbody> <?php $rank = 1; foreach ($popular_posts as $item): ?> <tr> <td><strong><?php echo $rank++; ?></strong></td> <td> <?php if ($item->post_title): ?> <a href="<?php echo get_edit_post_link($item->ID); ?>" target="_blank"> <?php echo esc_html($item->post_title); ?> </a> <?php else: ?> <em>Запись удалена (ID: <?php echo $item->ID; ?>)</em> <?php endif; ?> </td> <td> <span class="post-type-badge"><?php echo esc_html($item->post_type ?: 'N/A'); ?></span> </td> <td> <strong style="color: #d63638;"><?php echo number_format($item->view_count); ?></strong> </td> <td><?php echo $item->last_viewed ? date('d.m.Y H:i', strtotime($item->last_viewed)) : 'N/A'; ?></td> <td> <?php if ($item->post_title): ?> <a href="<?php echo get_permalink($item->ID); ?>" target="_blank" class="button button-small"> Смотреть </a> <?php endif; ?> </td> </tr> <?php endforeach; ?> </tbody> </table> <?php else: ?> <div style="background: #fff; border: 1px solid #ccd0d4; border-radius: 4px; padding: 40px; text-align: center; margin: 20px 0;"> <h3>Пока нет данных</h3> <p>Откройте несколько записей на сайте, чтобы начать собирать статистику просмотров.</p> </div> <?php endif; ?> <style> .pvc-stats-grid h3 { font-size: 1.1em; } .post-type-badge { background: #f0f0f1; color: #646970; padding: 2px 8px; border-radius: 3px; font-size: 11px; text-transform: uppercase; } </style> </div> <?php
}
// Добавляем колонку просмотров в список записей в админке
function pvc_add_views_column($columns)
{
$columns['post_views'] = 'Просмотры';
return $columns;
}
add_filter('manage_posts_columns', 'pvc_add_views_column');
add_filter('manage_pages_columns', 'pvc_add_views_column');
// Отображаем данные в колонке
function pvc_show_views_column($column, $post_id)
{
if ($column === 'post_views') {
$views = pvc_get_post_views($post_id);
echo $views ? '' . number_format($views) . '' : '0';
}
}
add_action('manage_posts_custom_column', 'pvc_show_views_column', 10, 2);
add_action('manage_pages_custom_column', 'pvc_show_views_column', 10, 2);
// Делаем колонку сортируемой
function pvc_sortable_views_column($columns)
{
$columns['post_views'] = 'post_views';
return $columns;
}
add_filter('manage_edit-post_sortable_columns', 'pvc_sortable_views_column');
add_filter('manage_edit-page_sortable_columns', 'pvc_sortable_views_column');
// Обрабатываем сортировку
function pvc_views_column_orderby($query)
{
if (!is_admin()) return;
$orderby = $query->get('orderby'); if ('post_views' === $orderby) { global $wpdb; $table_name = $wpdb->prefix . 'post_views'; $query->set('meta_query', array( 'relation' => 'OR', array( 'key' => 'post_views_temp', 'compare' => 'NOT EXISTS' ), array( 'key' => 'post_views_temp', 'value' => '', 'compare' => '=' ) )); $query->set('orderby', array( 'meta_value_num' => $query->get('order') )); // Добавляем JOIN с таблицей просмотров add_filter('posts_join', function($join) use ($wpdb, $table_name) { global $wpdb; $join .= " LEFT JOIN $table_name pv ON {$wpdb->posts}.ID = pv.post_id"; return $join; }); add_filter('posts_orderby', function($orderby) use ($wpdb) { $order = strtoupper($_GET['order'] ?? 'DESC'); return "COALESCE(pv.view_count, 0) $order"; }); }
}
add_action('pre_get_posts', 'pvc_views_column_orderby');
// Базовые стили для шорткодов
function pvc_add_frontend_styles()
{
if (!is_admin()) {
echo '';
}
}
add_action('wp_head', 'pvc_add_frontend_styles');