Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

Customising the CMS

Search Form, Results, Custom Fields


Reply

17 Posts   4225 Views

Avatar
stew

15 July 2010 at 11:08pm Community Member, 30 Posts

Barry you are a genius!

Works perfectly. The only bit that I can't workout is how to allow searching on multiple fields. At the moment I have this:

    $dos = DataObject::get('DatabaseEntry',"Address LIKE '".$strSearchQuery."'");

Just wondering how I can get it to search in Title, Category and Description as well... just don't know how, and now it's working don't want to break it all. lol.

Avatar
swaiba

15 July 2010 at 11:15pm Forum Moderator, 1796 Posts

Glad it worked out for you :)

The following code is fairly crude search, so if I put "Bristol city" in the search it will use LIKE '%Bristol%city%'..

$arrSearchQuery = explode(' ',$form->getSearchQuery());
$strSearchQuery = '%'.implode('%',$arrSearchQuery).'%';

$dos = DataObject::get('YOURDATAOBJECT',"FIELD LIKE '".$strSearchQuery."'");

if you wanted to search two fields just expand your where clause...

$dos = DataObject::get('YOURDATAOBJECT',
"FIELD LIKE '".$strSearchQuery."'"
." OR OTHERFIELD LIKE '".$strSearchQuery."'"
);

If you want to search over a couple of DataObject... just repeat the DataObject::get and then the "if ($dos){..." this will get more objects and then push them on the search results.

if you want one set higher than the other in the results change the " $p->Relevance = 1; " part

Barry

Avatar
stew

15 July 2010 at 11:19pm Community Member, 30 Posts

Yet again the silverstripe community comes through!

Thanks Barry, that extra bit of code worked perfectly, only a few bits left to do and the sites done :)

Avatar
stew

20 July 2010 at 12:07am Community Member, 30 Posts

Found a wee bit of a problem, if I enter a search term that is across two or more of the fields (ie. Category and Address) then I don't get any results, it just says nothing found.

Is there a way of tweaking the code slightly to allow it to search across multiple fields?

Avatar
swaiba

20 July 2010 at 12:59am Forum Moderator, 1796 Posts

As I said it is a bit crude, I don't have time to re-jig this right now, I can let you know later if I do. In the meantime you can try and do it yourself by...

1)repeating the whole thing afterwards like....

foreach ($arrSearchQuery as $strSearchQuery)
{
   $strSearchQuery = '%'.$strSearchQuery.'%';

   //repeat code to do DataOBject::get
   //add to $dosNewResults
}

2)
before the

//strip out the html from the results and append them to the results
//above - so that the ones with things to buy are first
if ($data['Results']->Count() > 0)

you will need to strip out the duplicates in some way... I'd suggest...

$dosNewRestults->removeDuplicates('URLSegment');

Barry

p.s. I'd really appreciate it if you had a go and posted a working version back as I'll update one of my sites using this bit of code :)

Avatar
stew

20 July 2010 at 1:10am Community Member, 30 Posts

Thanks for the code Barry, can't get it to work though :(

Here is the full code as it stands just now:

    /////////////////////////////////////////////////////////////
    // Start Custom

    $arrSearchQuery = explode(' ',$form->getSearchQuery());
    $strSearchQuery = '%'.implode('%',$arrSearchQuery).'%';

    $dos = DataObject::get('DatabaseEntry',"Address LIKE '".$strSearchQuery."'"."OR ContactWeb LIKE '".$strSearchQuery."'"."OR ContactPhone LIKE '".$strSearchQuery."'"."OR ContactEmail LIKE '".$strSearchQuery."'"."OR Category LIKE '".$strSearchQuery."'"." OR OrganisationName LIKE '".$strSearchQuery."'" );
   

    //make our our result set
    $dosNewRestults = new DataObjectSet();

    if ($dos)
    {
      $arr = $dos->toArray();
      foreach ($arr as $do)
      {
         $p = new Page();
         $p->Title = $do->OrganisationName;
         $p->URLSegment = 'SearchForm?POSTVAR='.$do->Address;;
         $p->Content = $do->Description;;
         $p->Address = $do->Address;;
         $p->Latitude = $do->Latitude;;
         $p->Longitude = $do->Longitude;;
         $p->ContactPhone = $do->ContactPhone;;
         $p->ContactWeb = $do->ContactWeb;;
         $p->ContactEmail = $do->ContactEmail;;
         $p->Category = $do->Category;;
         $p->ID = $do->ID;;
         $p->Relevance = 1;
         $p->CanViewType = 'Anyone';

         $dosNewRestults->push($p);
      }
      }
      foreach ($arrSearchQuery as $strSearchQuery)
      {
       $strSearchQuery = '%'.$strSearchQuery.'%';

       //repeat code to do DataOBject::get
       //add to $dosNewResults
      }
      
    //strip out the html from the results and append them to the results
    //above - so that the ones with things to buy are first
    if ($data['Results']->Count() > 0)
    {
    $arr = $data['Results']->toArray();
    foreach ($arr as $do)
    {
    $do->Content = strip_tags($do->Content);
    $dosNewRestults->push($do);
         $dosNewRestults->removeDuplicates('URLSegment');
    }
    }
   

   

    $data['Results'] = $dosNewRestults;
    // End Custom
    /////////////////////////////////////////////////////////////

As an additional thing that has only just come up as I've shown the client a quick demo of the system, they want to be able to choose which records are searchable. So within the DataObjectManager have a dropdown (or checkbox) which will say "Public" and then if it's marked as public it'll be included in the results, is there a quick way of doing that? I had a quick play with adding it as a "'AND Public LIKE'".1. but it didn't work.

Thanks again Barry :)

Avatar
swaiba

20 July 2010 at 1:23am Forum Moderator, 1796 Posts

for your public thing I'd do...

$dos = DataObject::get('DatabaseEntry',"(Address LIKE '".$strSearchQuery."'"."OR ContactWeb LIKE '".$strSearchQuery."'"."OR ContactPhone LIKE '".$strSearchQuery."'"."OR ContactEmail LIKE '".$strSearchQuery."'"."OR Category LIKE '".$strSearchQuery."'"." OR OrganisationName LIKE '".$strSearchQuery."') AND Public=1" );

(assuming public was an int field, if it was an enum or text then Public='Yes')

Avatar
stew

20 July 2010 at 1:25am Community Member, 30 Posts

Thanks Barry, I was quite close with it, lol. Still getting my head around Silverstripe (and PHP beyond the basic templating stuff.)