The solution is in this answer from WordPress Developers:
How to filter post listing (in WP dashboard posts listing) using a custom field (search functionality)?
First,youneedtoaddthedropdownandthetextinput,settingthePostTypeto$typenow
:
/***AdicionarfiltrodeCustomFieldsnatela/wp-admin/edit.php*/add_action('restrict_manage_posts','ba_admin_posts_filter_restrict_manage_posts');functionba_admin_posts_filter_restrict_manage_posts(){global$wpdb,$typenow;if($typenow!=='post')//AJUSTESEUPOSTTYPEreturn;$sql='SELECTDISTINCTmeta_keyFROM'.$wpdb->postmeta.'ORDERBY1';$fields=$wpdb->get_results($sql,ARRAY_N);?><selectname="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
}
Next, adding 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 fields with serialized arrays are not considered.
I tested this other solution to do the filtering and it 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 be functions.php
, but is more appropriate as a plugin .