Додаємо колонки у постів в адмінці (сортовані)
Поговоримо про створення нових колонок у таблиці записів (постів) у адмінці. Також розглянемо як зробити такі колонки сортованими, як, наприклад, сортується колонка дати. Так можна буде створити колонку з даними довільного поля, а потім сортувати записи, вибираючи потрібні. Робиться це просто.
У цій статті, наприклад, створимо колонку “Візити”, з даними довільного поля views, куди записуються відвідування. Колонка вийде сортована.

Хуки для створення колонок
- 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
Аналогічний першому – реєструє сортовану колонку, де ми вказуємо ім’я запиту orderby.
Також передає масив із зареєстрованими сортованими колонками. У разі фільтр виглядає так:
manage_edit-post_sortable_columns.- pre_get_posts
(wp-includes/query.php) Цей фільтр-дія спрацьовує на початку методу get_posts() класу WP_query.
Хук передає весь клас за посиланням (&$this). Використовуючи цей фільтр, ми можемо задати параметри головного запиту WP ($wp_query), яким потім будується висновок.
Щоб дізнатися , screen_id використовуємо функцію get_current_screen() . Її можна повісити на хук in_admin_header :
add_action( 'in_admin_header', function(){
echo '<pre>'. print_r( get_current_screen(), 1 ) .'</pre>';
} );
У нашому випадку screen_id = edit-postце сторінка редагування постів в адмінці.
Створюємо стовпчик
Вставляємо такий код у файл теми function.php :
// створюємо нову колонку
add_filter( 'manage_'.'post'.'_posts_columns', 'add_views_column', 4);
function add_views_column( $columns ){
$num = 2; // після якої колонки вставляти нові
$new_columns = array(
'views' => 'Візити',
);
return array_slice( $columns, 0, $num ) + $new_columns + array_slice( $columns, $num );
}
// Заповнюємо колонку даними
// wp-admin/includes/class-wp-posts-list-table.php
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 = asc (за замовчуванням)
// true = desc
return $sortable_columns;
}Тут ключ viewsповинен збігатися з ключем під час реєстрації колонки: $out['views']і $sortable_columns['views']. Значення: views_views буде значенням параметра запиту “orderby”, який WordPress додасть автоматично ( &orderby=views_views ). Це ж значення буде додано до параметрів запит WP_query і якщо воно співпадатиме зі значеннями відомими WP (‘title’, ‘date’, ‘modified’, ‘comment_count’ і т.д.), то WP сам відсортує колонку як потрібно і тут можна зупинитись. Повний список значень відомих WP , винятки становлять: meta_value та meta_value_num .
Якщо ми вкажемо meta_value замість views_views , WP не зможе автоматично виконати правильне сортування. Тому, якщо в параметрі orderby вказується наше значення views_views ( &orderby=views_views ), ми створимо кастомний, потрібний нам запит.
Для сортування за довільним полем, найпростіше змінити аргументи базового запиту, використовуючи хук pre_get_posts. Але важливо розуміти , що цей хук глобальний і спрацьовує щоразу, коли генерується сторінка і не тільки в адмінці, а й на фронті. Тому ми повинні точно вказати, у якому випадку змінювати запит, цим випадком у нас буде значення аргументу orderby = views_views . У решті випадків запит не чіпаємо.
Варіант 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: принцип такий самий, тільки використовується хук request :
// Змінюємо запит при сортуванні колонки
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: принцип взяв із статті Sortable Taxonomy Columns .
Тут ми змінюємо SQL запит, а не параметри, що передаються WP_query. Стане в нагоді, якщо потрібно створити якесь унікальне сортування. Переробив під наш випадок:
// Змінюємо запит при сортуванні колонки
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['where'] .= "AND {$wpdb->postmeta}.meta_key='views'";
$clauses['orderby'] = "{$wpdb->postmeta}.meta_value+0 ";
$clauses['orderby'] .= ( 'ASC' == strtoupper( $wp_query->get('order') ) ) ? 'ASC': 'DESC';
// ще елементи, що змінюються
//$clauses['groupby']
//$clauses['distinct']
//$clauses['fields'] // wp_posts.*
//$clauses['limits'] // LIMIT 0, 20
return $clauses;
}Пости із незаповненими довільними полями (його не існуватиме біля посту), не потраплять у вибірку.
Нотатка
Варіанти вище показують при сортуванні лише записи, які мають зазначене метаполі існує. Відсортувати так, щоб були і записи, у яких поля немає, складно! Для цього потрібно написати окремий складний запит. Набагато простіше і логічніше обійтися тим, що виходить…
Наприклад, так (або аналогічним способом) зробити не вийде :
Ширина колонки
Ще може стати в нагоді відредагувати ширину колонки, а то буває розтягується без потреби. Ширину вказуємо так:
// підправити ширину колонки через css
add_action('admin_head', 'add_views_column_css');
function add_views_column_css(){
echo '<style type="text/css">.column-views{ width:10%; }</style>';
}
Код повністю
/* Додаткові сортовані колонки для постів в адмінці
-------------------------------------------------- ---------------------- */
// створюємо нову колонку
add_filter('manage_post_posts_columns', 'add_views_column', 4);
function add_views_column( $columns ){
// видаляємо колонку Автор
//unset($columns['author']);
// Вставляємо в потрібне місце - 3 - 3-я колонка
$out = array();
foreach($columns as $col=>$name){
if(++$i==3)
$out['views'] = 'Візити';
$out[$col] = $name;
}
return $out;
}
// заповнюємо колонку даними - wp-admin/includes/class-wp-posts-list-table.php
add_filter('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);
}
}
// підправити ширину колонки через css
add_action('admin_head', 'add_views_column_css');
function add_views_column_css(){
if( get_current_screen()->base == 'edit')
echo '<style type="text/css">.column-views{width:10%;}</style>';
}
// додаємо можливість сортувати колонку
add_filter('manage_edit-post_sortable_columns', 'add_views_sortable_column');
function add_views_sortable_column($sortable_columns){
$sortable_columns['views'] = 'views_views';
return $sortable_columns;
}
// Змінюємо запит при сортуванні колонки
add_filter('pre_get_posts', 'add_column_views_request');
function add_column_views_request( $object ){
if( $object->get('orderby') != 'views_views' )
return;
$object->set('meta_key', 'views');
$object->set('orderby', 'meta_value_num');
}