WordPress tweak to manage posts admin, filter and show custom field

This tweak will change the “All Posts” page in the administration section of a WordPress site.

It adds the ability to filter the post list based on a custom field that has been used in any of the posts at any time.

If a custom field is selected but no filter value is given, all posts that contain any value in the custom field are listed.

Whether or not a value is provided, if a custom field is selected, that field will be added to the tabular view of posts. The custom field column is also made sortable (as is the Category column).

The following code should be added to the functions.php for your theme – or better still to a sub-theme.

/**
 * We will only do the following if we are on an ADMIN page
 */
if ( is_admin() ) {

	/** --- Add select menu to filter by custom field in admin & add filtered column to display table ---
	 * Based on: @see http://wpsnipp.com/index.php/functions-php/add-select-menu-to-filter-by-custom-field-in-admin/
	 * NB: Only ba_admin_posts_filter COULD run outside the manage posts page which is why it has an extra restriction inside
	 * @since 1.3.0 IT - Initial version
	 * 	Tidied up & wrapped in is_admin test so only loaded on admin pages,
	 * 	Added wildcard filtering and fixed ambiguous IF code in ba_admin_posts_filter,
	 * 	Added sortable column code,
	 * 	by Julian Knight 2012-01-09
	 */
		function ba_admin_posts_filter( $query ) {
			global $pagenow;
			if ( is_admin() && $pagenow=='edit.php' && isset($_GET['ADMIN_FILTER_FIELD_NAME']) && $_GET['ADMIN_FILTER_FIELD_NAME'] != '') {
				$query->query_vars['meta_key'] = $_GET['ADMIN_FILTER_FIELD_NAME'];
				// JK: Don't actually need default value - changing filter type to LIKE shows all posts with selected custom field set to anything
				//$query->query_vars['meta_value'] = '%';
				// JK: Change filter type to 'LIKE' instead of '='
				//		Doesn't work properly, partly because WP seems to filter % and * from input fields at source.
				$query->query_vars['meta_compare'] = 'LIKE';
				if (isset($_GET['ADMIN_FILTER_FIELD_VALUE']) && $_GET['ADMIN_FILTER_FIELD_VALUE'] != '') {
					$query->query_vars['meta_value'] = $_GET['ADMIN_FILTER_FIELD_VALUE'];
				}
			}
		}
		add_filter( 'parse_query', 'ba_admin_posts_filter' );
		function ba_admin_posts_filter_restrict_manage_posts() {
			global $wpdb;
			$sql = 'SELECT DISTINCT meta_key FROM '.$wpdb->postmeta.' ORDER BY 1';
			$fields = $wpdb->get_results($sql, ARRAY_N);
			printf( '<select name="ADMIN_FILTER_FIELD_NAME" title="%s"><option value="">%s</option>', 
					translate('Choose a custom field name. Add value to filter. Blank value shows the column and all posts with any value. Change to 1st entry in list to remove the filter.', 'baapf'),
					translate('Filter By Custom Fields', 'baapf')
				   );
			$current = isset($_GET['ADMIN_FILTER_FIELD_NAME'])? $_GET['ADMIN_FILTER_FIELD_NAME']:'';
			$current_v = isset($_GET['ADMIN_FILTER_FIELD_VALUE'])? $_GET['ADMIN_FILTER_FIELD_VALUE']:'';
			foreach ($fields as $field) {
				if (substr($field[0],0,1) != "_"){
				printf( '<option value="%s"%s>%s</option>',
						$field[0],
						$field[0] == $current? ' selected="selected"':'',
						$field[0]
					);
				}
			}
			printf( '</select> %s<input type="TEXT" name="ADMIN_FILTER_FIELD_VALUE" value="%s" title="%s"/>', 
					translate('Value:', 'baapf'),
					$current_v,
					translate('Leave blank to show all posts with the selected custom field set to SOMETHING. Does a wildcard search.', 'baapf')
				  );
		}
		add_action( 'restrict_manage_posts', 'ba_admin_posts_filter_restrict_manage_posts' );
		/* Register a custom column (based on: @see http://scribu.net/wordpress/custom-sortable-columns.html)
			and adds it to the edit-post page
			Changed to pick up the filter column specified above (if it is), if nothing selected, nothing is added
		 */
		function jk_custom_column_register( $columns ) {
			if ( isset($_GET['ADMIN_FILTER_FIELD_NAME']) && $_GET['ADMIN_FILTER_FIELD_NAME'] != '') {
				$columns[$_GET['ADMIN_FILTER_FIELD_NAME']] = __( $_GET['ADMIN_FILTER_FIELD_NAME'], 'my-plugin' );
			}
			return $columns;
		}
		add_filter( 'manage_edit-post_columns', 'jk_custom_column_register' );
		// Display the column content on the manage posts page
		function jk_custom_column_display( $column_name, $post_id ) {
			if ( isset($_GET['ADMIN_FILTER_FIELD_NAME']) && $_GET['ADMIN_FILTER_FIELD_NAME'] != '') {
				if ( $_GET['ADMIN_FILTER_FIELD_NAME'] != $column_name )
					return;
			 
				$custcol = get_post_meta($post_id, $_GET['ADMIN_FILTER_FIELD_NAME'], true);
				if ( !$custcol )
					$custcol = '<em>' . __( 'undefined', 'my-plugin' ) . '</em>';
			 
				echo $custcol;
			}
		}
		add_action( 'manage_posts_custom_column', 'jk_custom_column_display', 10, 2 );
		// How should WP sort this column?
		function jk_custom_column_orderby( $vars ) {
			if ( isset($_GET['ADMIN_FILTER_FIELD_NAME']) && $_GET['ADMIN_FILTER_FIELD_NAME'] != '') {
				if ( isset( $vars['orderby'] ) && $_GET['ADMIN_FILTER_FIELD_NAME'] == $vars['orderby'] ) {
					$vars = array_merge( $vars, array(
						'meta_key' => $_GET['ADMIN_FILTER_FIELD_NAME'],
						'orderby' => 'meta_value'  // 'meta_value_num' or 'meta_value'
					) );
				}
			}
			return $vars;
		}
		add_filter( 'request', 'jk_custom_column_orderby' );
		// Register some extra columns as sortable on the edit posts page
		function jk_column_register_sortable( $columns ) {
			if ( isset($_GET['ADMIN_FILTER_FIELD_NAME']) && $_GET['ADMIN_FILTER_FIELD_NAME'] != '') {
				$columns[$_GET['ADMIN_FILTER_FIELD_NAME']] = $_GET['ADMIN_FILTER_FIELD_NAME'];
			}
			$columns['categories'] = 'categories';	 
			// $columns['tags'] = 'tags'; // doesn't work correctly as tags are multi-valued?
			return $columns;
		}
		add_filter( 'manage_edit-post_sortable_columns', 'jk_column_register_sortable' );
	/** --- End of Filter Manage Post page by custom field --- **/
	
} // ---- End of is_admin ----
  • Hi, it is really hard for me to understand the codes but it works on my wordpress and it simply filters all the post in my WordPress blog. Thanks!