Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Is there an easy way to obtain a list of uniqye custom fields value from a specified taxonomy value?

For example, I have many categories under taxonomy "products". Every product has some custom fields, for example: "color", that I use to build a tag with a list of available product colors.

When i select a product category (f. ex. "Cars"), I wish to filter out the colors that are NOT included in the selected category. In other words, if NO car is brown, "Brown" (though it is a value that is present in other product categories) should not be listed.

The same thing should happen when I select another custom field value (f. ex., "year" on "2010". If no product of year 2010 is "red", "red" should be filtered out).

Any suggestions?

share|improve this question

1 Answer 1

The filtering can be done with this function totally untested

function filter_custom_fields($key='', $terms='', $tax='', $selkey='', $selval='') {
   global $wpdb;
   $include = '';
   if ( $selkey && $selval && ( is_string($selval) || is_array($selval) ) ) {
     $include = " AND post_id IN (" . 
                 $wpdb->prepare("SELECT DISTINCT post_id FROM $wpdb->postmeta
                 WHERE meta_key = %s AND meta_value ", $selkey );
     if ( is_array($selval) ) {
        $selvals = '';
        foreach ( $selval as $val ) {
            if ( $selvals != '' ) $selvals .= ',';
            $selvals .= $wpdb->prepare('%s', $val);
        }
        $include .= "IN ($selvals))";
     } else {
        $include .= $wpdb->prepare( "= %s)", $selval );
     }
   }
   if ( ! empty( $terms ) ) { 
      if ( is_array($terms) ) {
        $terms = array_map('intval', $terms );
        $ttis = $wpdb->get_col("SELECT term_taxonomy_id FROM 
                $wpdb->term_taxonomy WHERE 
                term_id IN (" . implode(',', $terms ) . ")");
        if ($ttis) {
          $include .= " AND post_id IN (SELECT DISTINCT object_id
             FROM $wpdb->term_relationships WHERE
             term_taxonomy_id IN (" . implode(',', $ttis) . "))";
          }
      } else {        
        $field = is_numeric($terms) ? 'id' : 'slug';
        $term_obj = get_term_by( $field, $terms, $tax);
        if ( $term_obj && ! is_wp_error($term_obj) ) {
           $include .= ' AND post_id IN (' . $wpdb->prepare(
             "SELECT DISTINCT object_id FROM $wpdb->term_relationships WHERE
             term_taxonomy_id = %d", $term_obj->term_taxonomy_id
           ) . ")";
        }
      }
   }
   $query = $wpdb->prepare(
            "SELECT DISTINCT meta_value FROM $wpdb->postmeta WHERE meta_key = %s",
            $key);
   if ( $include ) $query .= $include;
   $meta = $wpdb->get_col($query); 
   if ( $meta ) return array_map('maybe_unserialize', $meta);
}

As asked, the function above can

  • filter out a custom field by a taxonomy term
  • filter out a custom field by a another custom field

But can do more:

  • filter out by more than one taxonomy term
  • filter out by more than one custom field
  • filter out by more than one taxonomy term by another custom field
  • filter out by a taxonomy term and by more than one custom field
  • filter out by more than one taxonomy term and by more than one custom field

Moreover, function gives you flexibility to choose the taxonomy: one custom tax as you asked, or category or post...

How use it:

Filtering by a taxonomy term

$cars_colors = filter_custom_fields('color', 'cars', 'products');

Third param is for taxonomy, so you can use with taxonomy you need. Note that you have to use term slug or term id and not term name.

Filtering by another custom field

$colors_2010 = filter_custom_fields('color', false, false, 'year', '2010');

Self explanatory, I think.

Filtering by a taxonomy term and by another custom field

$cars_colors_2010 = filter_custom_fields('color', 'cars', 'products', 'year', '2010');

Filtering by multiple taxonomy term

$cars_and_moto_colors = filter_custom_fields('color', array(12,13), 'products');

Filtering by multiple values of another custom field

$colors_2009_2010_2011 = filter_custom_fields('color', false, false, 'year', array('2009', '2010', '2011'));

Filtering by multiple taxonomy term and multiple values of another custom field

$cars_and_moto_colors_2009_2010_2011 = filter_custom_fields('color', array(12,13), 'products', 'year', arary('2009', '2010', '2011'));

Just a note. You wrote nothing about post types. This function works not taking into accounts post types, so if custom field and/or taxonomy you want to filter by are assigned to different post types it may not work as expected.

Hope it helps (and hope it works).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.