Додаємо колонки у постів в адмінці (сортовані)

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

У цій статті, наприклад, створимо колонку “Візити”, з даними довільного поля views, куди записуються відвідування. Колонка вийде сортована.

dop


Хуки для створення колонок

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;
}

Пости із незаповненими довільними полями (його не існуватиме біля посту), не потраплять у вибірку.

Нотатка

Варіанти вище показують при сортуванні лише записи, які мають зазначене метаполі існує. Відсортувати так, щоб були і записи, у яких поля немає, складно! Для цього потрібно написати окремий складний запит. Набагато простіше і логічніше обійтися тим, що виходить…

Наприклад, так (або аналогічним способом) зробити не вийде :

// НЕРОБОЧИЙ КІД!
add_action( 'pre_get_posts', 'pre_get_posts_views');
function pre_get_posts_views( $wp_query ) {

		$wp_query->set( 'orderby', 'views_exists' );

		$wp_query->set( 'meta_query', [
			'relation' => 'OR',
			'views_exists' => [
				'key' => 'views',
				'compare' => 'EXISTS',
				'type' => 'numeric',
			],
			[
				'key' => 'views',
				'compare' => 'NOT EXISTS',
			],
		]);
	}
}


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

Ще може стати в нагоді відредагувати ширину колонки, а то буває розтягується без потреби. Ширину вказуємо так:

// підправити ширину колонки через 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');
}

Залишити коментар

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *