You are here:  » Partial search and filter using custom fields


Partial search and filter using custom fields

Submitted by bingobongo on Wed, 2014-12-24 01:30 in

Hi there,

Hope you can maybe help with an issue i'm having. I've added an extra field for 'colors' and where i'm saving multiple values into a 'colors' column within the 'products' table.

I'm saving them as serialized arrays (not sure if this is a good or bad thing), with sample data like:

a:5:{i:0;s:7:"#000000";i:1;s:7:"#424153";i:2;s:7:"#E7D8B1";i:3;s:7:"#CC6633";i:4;s:7:"#CCCCCC";}

I've amended search.php to include:

  if ($colorsFilter)
  {
     $priceWhere .= " AND colors LIKE '%".database_safe($colorsFilter)."%' ";
  }

However, this doesn't seem to be working. If I change the row in the database to '000000' and use '000000' as the search variable, the search works, but if I try to search within the full array above, it doesn't work.

What's the best way to go about this, and possibly to search multiple colors at once too e.g. CCCCCC, 000000, 424153?

Thanks!

Submitted by support on Wed, 2014-12-24 12:26

Hi,

Did you check with a database tool (e.g. phpMyAdmin), or by temporarily adding to the output of your product pages using <?php print $mainProduct["colors"]; ?> that the value was imported correctly before making the manual override as the $priceWhere code looks absolutely fine... I use the same technique all the time helping users work with comma separated strings, so should be no problem.

To support filtering for multiple values, you'd need to first change the filter input select box to support multi-select by adding multiple='multiple' and then you can also add a size attribute.

With that in place, edit search.php and make the following replacements:

Look for the following code at line 18:

  $brandFilter = (isset($_GET["brandFilter"])?$_GET["brandFilter"]:"");

...and REPLACE with:

  $colorsFilter = ($_GET["colorsFilter"]?$_GET["colorsFilter"]:array());

Look for the following code at line 65:

  if ($brandFilter)
  {
    $priceWhere .= " AND brand = '".database_safe($brandFilter)."' ";
  }

...and REPLACE with:

  if ($brandFilter)
  {
    $priceWhere .= " AND brand = '".database_safe($brandFilter)."' ";
  }
  if (count($colorsFilter))
  {
    $wheres = array();
    foreach($colorsFilter as $v)
    {
      $wheres[] = " colors LIKE '%".database_safe($v)."%' ";
    }
    $priceWhere .= " AND (".implode(" OR ",$wheres).") ";
  }

Look for the following code at line 350:

      if ($brandFilter)
      {
        $sortHREF .= "brandFilter=".urlencode($brandFilter)."&amp;";
      }

...and REPLACE with:

      if ($brandFilter)
      {
        $sortHREF .= "brandFilter=".urlencode($brandFilter)."&amp;";
      }
      if (count($colorsFilter))
      {
        foreach($colorsFilter as $v)
        {
          $sortHREF .= "colorsFilter[]=".urlencode($v)."&amp;";
        }
      }

...and finally look for the following code at line 472:

    if ($brandFilter)
    {
      $sort .= "&amp;brandFilter=".urlencode($brandFilter);
    }

...and REPLACE with:

    if ($brandFilter)
    {
      $sort .= "&amp;brandFilter=".urlencode($brandFilter);
    }
    if (count($colorsFilter))
    {
      foreach($colorsFilter as $v)
      {
        $sort .= "&amp;colorsFilter[]=".urlencode($v);
      }
    }

Hope this helps! If the db value looks OK and the LIKE clause still appears to be not working let me know and I'll check it out further with you...

Cheers,
David.
--
PriceTapestry.com

Submitted by bingobongo on Sun, 2014-12-28 23:17

Thanks David for the quick response! Really appreciated. However, it didn't seem to work at all and is giving me null index errors :( I've tried following the steps above with a fresh install and the install I had already.

What would the modifications be like - from scratch - to add on an extra custom field for 'colour' but populated with 'colour' populated with an array like:

a:5:{i:0;s:7:"#000000";i:1;s:7:"#424153";i:2;s:7:"#E7D8B1";i:3;s:7:"#CC6633";i:4;s:7:"#CCCCCC";}

...and to make the extra field 'colour' searchable and filterable in addition to the core fields (brand/category/price etc). For clarity, i'm on the 14/06A release if that helps :)

Submitted by support on Mon, 2014-12-29 11:06

Hi,

Please could email me from your current email address with a copy of the search.php that you would like to use and I'll modify that for you for colour filter with multiple select and include the dbmod required to add the new field. I would forward but the email address on your account is 6 years old and I did see a message delivery error recently when I think you tried to reset your forum password so this way I'll pick up your latest email address and forward the mods to you...

Thanks!

David.
--
PriceTapestry.com

Submitted by bingobongo on Sun, 2015-01-11 22:03

Thanks David for great support - the search.php which you sent works a treat!

What's the best way to add a filter to include the colors in the /html/ templates? I can't seem to figure out the best way to explode the arrays of the search results and show them as a 'color' filter. Would love some guidance here.

Also - what are the chances of getting a 'sneak peak' of the "reverse map" feature for categories mentioned at http://www.pricetapestry.com/node/5541? This would be super useful for the site i'm building at the moment.

Thanks again!

Submitted by support on Tue, 2015-01-13 09:11

Hi,

I've helped a number of users extract comma separated lists out into a single values for use in filters, so this is essentially the same, but using the array as the source instead. Consider the following, which you should be able to insert into html/searchfilters.php as required...

$sql1 = "SELECT DISTINCT(color) FROM `".$config_databaseTablePrefix."products` WHERE ".$where.$priceWhere." AND color <> '' ORDER BY color";
if (database_querySelect($sql1,$rows1))
{
  // extract unique colors from unserialized array into new array
  $newRows1 = array();
  foreach($rows1 as $row)
  {
    $colors = unserialize($row["color"]);
    foreach($colors as $color)
    {
      $color = trim($color);
      $newRows1[$color]["color"] = $color;
    }
  }
  // sort unique color list
  ksort($newRows1);
  $rows1 = $newRows1;
  // standard filter code from here
  print "<div class='small-12 medium-2 columns'>";
  print "<label>Color<br />";
  print "<select name='colorFilter'>";
  print "<option value=''>".translate("All")."</option>";
  foreach($rows1 as $row)
  {
    $selected = ($colorFilter==$row["color"]?"selected='selected'":"");
    print "<option value='".htmlspecialchars($row["color"],ENT_QUOTES,$config_charset)."' ".$selected.">".$row["color"]."</option>";
  }
  print "</select>";
  print "</label>";
  print "</div>";
}

Hope this helps!

Live demo site of 15/01 with reverse mapping will be online very soon!

Cheers,
David.
--
PriceTapestry.com