WordPress как на ладони
wordpress jino

Дополнительные сортируемые колонки у постов в админке

Поговорим о создании своих колонок в таблице постов в админ-панели. С версии 3.1 колонки в админке можно сортировать, упорядочивать по дате, названию статьи. Также, можно создать свою колонку с возможностью сортировки постов по ней. Это удобно, например: создать колонку с данными произвольного поля и по этой колонке потом сортировать посты, выбирая нужные. А самое главное, сделать это не очень сложно. Эта статья — основа для создания , жаль, что он не общедоступен.

dop

В этой статье, в качестве примера, создадим колонку "Визиты", с данными произвольного поля 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(). В нашем случае $screen->id = edit-post - страница редактирования постов в админке. get_current_screen можно, например, повесить на хук in_admin_header:

add_action('in_admin_header', 'my_get_current_screen');
function my_get_current_screen(){
	$screen_info = get_current_screen();

	echo '<pre>';
	print_r($screen_info);
	echo '</pre>';
}

Создаем колонку

Вставляем такой код в файл темы 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 );
}

// заполняем колонку данными
add_filter('manage_post_posts_custom_column', 'fill_views_column', 5, 2); // wp-admin/includes/class-wp-posts-list-table.php
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'] = array('views_views', 'desc'); // 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.

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

Вариант 1:

// изменяем запрос при сортировке колонки
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');
}

Вариант 2: принцип точно такой же, только используется хук request:

// изменяем запрос при сортировке колонки
add_filter('request', 'add_column_views_request');
function add_column_views_request( $vars ) {
	if ( 'views_views' == $vars['orderby'] ){
		$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');
}

Http://kazinodrift.5000rubley.com/

http://kazinodrift.5000rubley.com/

kazinodrift.5000rubley.com

Дополнительные сортируемые колонки у постов в админке 30 комментариев
Вопросы 2 Все
  • Александр

    У Вас хороший ресурс, но начанающим не все понятно, подскажите пожалуйста, что в этой записи обозначает цифра 4, третий передаваемый параметр

    add_filter('manage_edit-post_columns', 'add_views_column', 4);

    Ответитьгод назад #
    • Kama4659

      Приоритет, выполнения функции в момоент срабатывания хука. К хуку может быть подключено много функций, так вот это приоритет. Прочитайте о приоритетах в этом описании.

      Ответитьгод назад #
  • Mina

    Почему-то не заполняется столбец. даже простое echo "blablabla"; не отображается в таблице. В чем может быть проблема?

    Ответитьгод назад #
  • Кирилл @
    if( colname === 'views' ){
    	echo get_post_meta($post_id, 'views', 1);   
    }

    colname - пропущен $

  • Руслан

    Бился пол-дня - так и не удалось сделать сортировку по полю "Event_date" в пользовательском типе "Event"... Очень расстроен. Сортировка проходит по столбцу то-ли "ID", то-ли "Дата публикации", но только не по моему столбцу. Хотя все фильтры отработали правильно, и в столбце выводятся правильные данные

  • campusboy1946 cайт: www.youtube.com/c/wpplus

    Отличный пост для старта! Особенно цена, даже уникальна, инфа, как изменить sql запрос.

    • campusboy1946 cайт: www.youtube.com/c/wpplus

      Заметил, что если сделать быстрое редактирование поста, то данные по такой колонки исчезают из вида.

      • Kama4659

        Это потому что фильтр основан на screen а при аякс запросе данных скрина нет судя по всему и фильтр не срабатывает... Странно что это не продумано в движке... Должно быть какое-то решение в виде костыля скорее всего...

        Там вон есть аналогичный фильтр manage_(post_type)_posts_columns надо его использовать и скорее всего все будет как надо...

  • Владимир

    Подскажите, малец в тупике, как сделать сортировку по другим данным, числа. В конкретно моем случае это "имена" родительской категории к категории поста.
    Вывожу я их так:

    function fill_views_column( $colname, $post_id ){
    	if( $colname === 'views' ){
    		$post_data = wp_get_object_terms( $post_id, 'magasine' );
    		$parent = get_term(  $post_data[0]->parent, 'magasine' );
    		echo $parent->name;
    	}
    }
    

    А как сделать по этим данным сортировку допендрить не могу.
    Сортировка по полу в принципе включена но она не работает как предполагалось, то есть не сортирует вывод по значению поля, а по id постов, к слову это своя таксономия и тип постов.
    Сами значения в коде выше это года.

    Ответить18 дней назад #

Здравствуйте, !

Ваш комментарий