Додаємо колонки у постів в адмінці (сортовані)
Поговоримо про створення нових колонок у таблиці записів (постів) у адмінці. Також розглянемо як зробити такі колонки сортованими, як, наприклад, сортується колонка дати. Так можна буде створити колонку з даними довільного поля, а потім сортувати записи, вибираючи потрібні. Робиться це просто.
У цій статті, наприклад, створимо колонку “Візити”, з даними довільного поля 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'); }