Searching by custom attribute values (select/checkboxes)

Permalink
Hi all

I've created a custom attribute which stores a serialized string which contains page IDs, which are associated with the relevant page's name, which the user clicks to choose. The stored data looks like this:

a:1:{s:5:"value";a:2:{i:0;s:3:"166";i:1;s:3:"167";}}


I'd like to be able to search this attribute using the page names.

I've managed to display the existing values easily enough by creating search.php in /models/attribute/type/page_selector/, which looks like this:

foreach ($options as $key=> $option) {
   ?>
   <label class="checkbox inline">
      <input type="checkbox" name="<?=$fieldPostName?>[]" value="<?=$key?>"/> <?=$option?>
   </label>
   <?php
   }


The search() function in controller.php gets a Page List of the available pages for that instance of the attribute. This displays correctly, but I need to create some logic in searchForm() in controller.php (I think) to actually perform the search.

The searchForm() function in the Select attribute's controller.php seems like a good place to start, but I'm a bit perplexed by the last foreach and what $multiString is designed to do:

public function searchForm($list) {
      $options = $this->request('atSelectOptionID');
      $optionText = array();
      $db = Loader::db();
      $tbl = $this->attributeKey->getIndexedSearchTable();
      if (!is_array($options)) {
         return $list;
      }
      foreach($options as $id) {
         if ($id > 0) {
            $opt = SelectAttributeTypeOption::getByID($id);
            if (is_object($opt)) {
               $optionText[] = $opt->getSelectAttributeOptionValue(true);
               $optionQuery[] = $opt->getSelectAttributeOptionValue(false);
            }


Any thoughts or ideas on this would be really helpful :)

melat0nin
 
melat0nin replied on at Permalink Best Answer Reply
melat0nin
Whoah, I seem to have managed it. I'm probably missing something, but the select attribute's searchForm() function seems to be a bit overcomplex.

Anyway, first I've created my custom attribute and stored it as a serialised string using \n as the separator, in line with other similar functionality in c5 (I had previously used PHP's serialize() function but that caused complications at the searching stage):

/models/attribute/my_attribute/controller.php:

// Save the attribute's data
public function saveForm($data){
    $valueArray = $data['value'];
    $valueString = implode("\n", $valueArray);
    if (empty($valueString)) {
        $this->saveValue('');
    } else {
        $this->saveValue("\n{$valueString}\n");
    }
}
// searchForm() is called by c5's Page Search page -- overrides default attribute searchForm() function
public function searchForm($list) {
    // These are the attribute search terms, in this case checkboxes with cIDs as their values
    $terms = $this->request('value');
    // If no term(s) specified, just return the unfiltered list


It's also worth creating a custom getDisplayValue() function to format how search results should look. In my case, the data that's stored is just page IDs, so outputting '123, 456' as the search result isn't exactly intuitive. getDisplayValue() takes care of this:

/*
* Display the correct values (page names) in search results
*/
public function getDisplayValue() {
    $results = $this->getValue();
    $results = explode("\n", trim($results));
    $string = '';
    // Loop throught results and find/process data as required
    foreach ($results as $result) {
        $page = Page::getByID($result);
        $string .= $page->getCollectionName() . ', ';
    }
    $string = substr($string, 0, strlen($string)-2);
    return $string;
}


This outputs a snazzy list of page names which match the IDs of the attribute options the user has searched for.

Hope this helps someone.