The solution lies in this answer from Wordpress Developers:
How to filter post Listing (in WP Dashboard posts Listing) using a custom field (search Functionality)?
First, you need to add the dropdown and text input by adjusting the Post Type in comparison to $typenow
:
/**
* Adicionar filtro de Custom Fields na tela /wp-admin/edit.php
*/
add_action( 'restrict_manage_posts', 'ba_admin_posts_filter_restrict_manage_posts' );
function ba_admin_posts_filter_restrict_manage_posts()
{
global $wpdb, $typenow;
if( $typenow !== 'post' ) // AJUSTE SEU POST TYPE
return;
$sql = 'SELECT DISTINCT meta_key FROM '.$wpdb->postmeta.' ORDER BY 1';
$fields = $wpdb->get_results( $sql, ARRAY_N );
?>
<select name="ADMIN_FILTER_FIELD_NAME">
<option value=""><?php _e('Filter By Custom Fields', 'baapf'); ?></option>
<?php
$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 )
{
# Hidden fields
if ( substr( $field[0], 0, 1 ) != "_" )
{
printf(
'<option value="%s"%s>%s</option>',
$field[0],
$field[0] == $current ? ' selected="selected"' : '',
$field[0]
);
}
}
?>
</select>
<?php _e('Value:', 'baapf'); ?>
<input type="TEXT" name="ADMIN_FILTER_FIELD_VALUE" value="<?php echo $current_v; ?>" />
<?php
}
Then add the filter when the search happens inside the page /wp-admin/edit.php
and the $_GET
correct is set:
/**
* Fazer a filtragem conforme o $_GET
*/
add_filter( 'parse_query', 'ba_admin_posts_filter' );
function ba_admin_posts_filter( $query )
{
global $pagenow;
$get_url = isset($_GET['ADMIN_FILTER_FIELD_NAME']) && $_GET['ADMIN_FILTER_FIELD_NAME'] != '';
if ( is_admin() && $pagenow=='edit.php' && $get_url )
{
$query->query_vars['meta_key'] = $_GET['ADMIN_FILTER_FIELD_NAME'];
if (isset($_GET['ADMIN_FILTER_FIELD_VALUE']) && $_GET['ADMIN_FILTER_FIELD_VALUE'] != '')
$query->query_vars['meta_value'] = $_GET['ADMIN_FILTER_FIELD_VALUE'];
}
}
Note that the search is literal by "Value" and that the Fields with arrays serialized are not considered.
I tested this other solution for filtering and seems to work with serialized Fields (deeper tests are needed):
add_filter( 'posts_clauses', 'wpse143477_parse_clauses', 10, 2 );
function wpse143477_parse_clauses($clauses, $query) {
global $pagenow, $wpdb;
$get_url = isset($_GET['ADMIN_FILTER_FIELD_NAME']) && $_GET['ADMIN_FILTER_FIELD_NAME'] != '';
if ( is_admin() && $pagenow=='edit.php' && $get_url )
{
$keyword = $_GET['ADMIN_FILTER_FIELD_VALUE'];
$keyword = '%' . like_escape( $keyword ) . '%';
$post_ids = $wpdb->get_col( $wpdb->prepare( "
SELECT DISTINCT post_id FROM {$wpdb->postmeta}
WHERE meta_key = '%s' AND meta_value LIKE '%s'
", $_GET['ADMIN_FILTER_FIELD_NAME'], $keyword ) );
if( !empty( $post_ids )) {
$clauses['where'] .= " AND {$wpdb->posts}.ID IN (" . implode( ', ', $post_ids ) . ')';
}
}
return $clauses;
}
PS: This type of code can go functions.php
, but it is more appropriate as a plugin.
So it turns out that what I really want is that you don’t have to include dropdown. I want to search in that standard text field and have it bring the matches of all fields in the database. It is as?
– Igor Barreto
@Igorbarreto, to edition you suggested is more appropriate as a comment. In Help Center has more details.
– brasofilo
Well, I adapted the answer to your remark.
– brasofilo