Добавление колонок в записи в админке с сортировкой: шаг за шагом

## Добавление колонок в записи в админке (с сортировкой)

В этой статье мы поговорим о том, как добавить новые колонки в таблицу записей в админской области WordPress. Мы также рассмотрим, как сделать эти колонки сортируемыми, подобно колонке с датой. Это позволит нам создать колонку с данными из метаполя и сортировать записи на основе этих данных. На самом деле, это довольно просто.

### Содержание:

- Хуки для создания колонок
- Создание колонки
- Сделать колонку сортируемой
- Ширина колонки
- Полный код (в виде класса)

В качестве примера мы создадим колонку "Посещения" с данными из метаполя views, где будут записываться количество визитов. Эта колонка будет сортируемой.

![Пример таблицы записей](https://example.com/image.png)

### Хуки для создания колонок

- manage_(screen_id)_columns  
  Этот хук позволяет добавлять колонки в таблицу записей на указанном экране (в нашем случае — edit-post). Мы передаем массив с данными колонок, который можем изменить, добавив свою колонку (views) или удалив существующую с помощью unset(). Название нашего фильтра будет: manage_edit-post_columns.

- manage_(post_type)_posts_columns  
  Похож на предыдущий — добавляет колонки, но здесь указывается тип записи, а не ID экрана. Название фильтра: manage_post_posts_columns. С версии 3.1 рекомендуется использовать этот хук.

- manage_(post_type)_posts_custom_column  
  Используется для заполнения данных колонки на странице записей. В нашем случае: manage_post_posts_custom_column. Он передает имя колонки и ID записи.

- manage_(screen_id)_sortable_columns  
  Регистрирует сортируемую колонку, где мы указываем название параметра для сортировки.

- pre_get_posts  
  Этот фильтр срабатывает в самом начале метода get_posts() класса WP_Query. Он позволяет установить параметры основного WP-запроса ($wp_query).

Для определения screen_id используем функцию get_current_screen(). Её можно подключить через действие in_admin_header:

```php
add_action('in_admin_header', function(){
    echo '
'. print_r(get_current_screen(), 1) .'

';
});

В нашем случае, screen_id = edit-post — это страница редактирования записей в админке.

Создание колонки

Вставьте следующий код в файл functions.php вашей темы:

// создать новую колонку
add_filter('manage_' . 'post' . '_posts_columns', 'add_views_column', 4);
function add_views_column($columns) {
    $num = 2; // после какой колонки вставить новую

    $new_columns = [
        'views' => 'Посещения',
    ];

    return array_slice($columns, 0, $num) + $new_columns + array_slice($columns, $num);
}

// заполнить колонку данными
add_action('manage_' . 'post' . '_posts_custom_column', 'fill_views_column', 5, 2);
function fill_views_column($colname, $post_id) {
    if ($colname === 'views') {
        echo get_post_meta($post_id, 'views', 1);
    }
}

На этом этапе мы можем остановиться, если не нужно сортировать колонку — она просто отобразит данные.

Сделать колонку сортируемой

// добавить возможность сортировки колонки
add_filter('manage_edit-' . 'post' . '_sortable_columns', 'add_views_sortable_column');
function add_views_sortable_column($sortable_columns) {
    $sortable_columns['views'] = ['views_views', false];
    // false = по возрастанию (по умолчанию)
    // true = по убыванию

    return $sortable_columns;
}

Здесь значение views должно совпадать с ключом при регистрации колонки: $out['views'] и $sortable_columns['views']. Значение views_views будет параметром запроса для сортировки, который WordPress добавит автоматически (&orderby=views_views).

Если мы укажем meta_value вместо views_views, WP не сможет автоматически выполнить правильную сортировку. Чтобы сортировать по метаполю, проще всего изменить аргументы базового запроса с помощью хука pre_get_posts. Но важно понимать, что этот хук глобальный и срабатывает каждый раз, когда генерируется страница. Поэтому мы должны точно указать, когда модифицировать запрос.

Вариант 1:

// изменить запрос при сортировке колонки
add_action('pre_get_posts', 'add_column_views_request');
function add_column_views_request($query) {
    if (!is_admin() || !$query->is_main_query() || $query->get('orderby') !== 'views_views' || get_current_screen()->id !== 'edit-post') {
        return;
    }

    $query->set('meta_key', 'views');
    $query->set('orderby', 'meta_value_num');
}

Вариант 2:

// изменить запрос при сортировке колонки
add_filter('request', 'add_column_views_request');
function add_column_views_request($vars) {
    if (isset($vars['orderby']) && $vars['orderby'] === 'views_views') {
        $vars['meta_key'] = 'views';
        $vars['orderby'] = 'meta_value_num';
    }

    return $vars;
}

Вариант 3:

// изменить запрос при сортировке колонки
add_filter('posts_clauses', 'add_column_views_request', 10, 2);
function add_column_views_request($clauses, $wp_query) {
    if ('views_views' != $wp_query->query['orderby']) {
        return $clauses;
    }

    global $wpdb;

    $clauses['join'] .= " LEFT JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID={$wpdb->postmeta}.post_id";
    $clauses['orderby'] = " {$wpdb->postmeta}.meta_value + 0 ";
    $clauses['orderby'] .= ('ASC' == strtoupper($wp_query->get('order'))) ? 'ASC' : 'DESC';

    return $clauses;
}

Обратите внимание, что записи с пустыми метаполями (где мета-ключ не существует) не будут включены в выборку.

Ширина колонки

Также может быть полезно отредактировать ширину колонки, так как иногда она растягивается без необходимости. Указываем ширину следующим образом:

// подправить ширину колонки через CSS
add_action('admin_head', 'add_views_column_css');
function add_views_column_css() {
    echo '';
}

Полный код (в виде класса)

/**
 * Дополнительные сортируемые колонки для записей в админке
 */
final class My_Sortable_Post_Columns {

    public static function init() {
        // создать новую колонку
        add_filter('manage_post_posts_columns', [__CLASS__, 'add_columns'], 4);
        // заполнить колонку данными
        add_filter('manage_post_posts_custom_column', [__CLASS__, 'fill_columns'], 5, 2);
        // подправить ширину колонки через CSS
        add_action('admin_head', [__CLASS__, '_css']);
        // добавить возможность сортировать колонку
        add_filter('manage_edit-post_sortable_columns', [__CLASS__, 'add_sortable_columns']);
        // изменить запрос при сортировке колонки
        add_filter('pre_get_posts', [__CLASS__, 'handle_sort_request']);
    }

    public static function add_columns($columns) {
        $out = [];
        foreach ($columns as $col => $name) {
            if (++$i == 3) {
                $out['views'] = 'Посещения';
            }
            $out[$col] = $name;
        }

        return $out;
    }

    public static function add_sortable_columns($sortable_columns) {
        $sortable_columns['views'] = 'views_views';

        return $sortable_columns;
    }

    public static function fill_columns($colname, $post_id) {
        if ($colname === 'views') {
            echo get_post_meta($post_id, 'views', 1);
        }
    }

    public static function _css() {
        if ('edit' === get_current_screen()->base) {
            echo '';
        }
    }

    public static function handle_sort_request($object) {
        if ($object->get('orderby') != 'views_views') {
            return;
        }

        $object->set('meta_key', 'views');
        $object->set('orderby', 'meta_value_num');
    }
}

Теперь вы знаете, как добавить кастомные колонки в записи WordPress и сделать их сортируемыми. Это поможет вам лучше организовать данные в админской панели.

Leave a Reply

Ваш адрес email не будет опубликован. Обязательные поля помечены *