Jump to:

1976 Posts in 1306 Topics by 607 members

Form Questions

SilverStripe Forums » Form Questions » Problem with search and scaffolded searchform

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Page: 1 2
Go to End
Author Topic: 2524 Views
  • Euphemismus
    Avatar
    Community Member
    82 Posts

    Problem with search and scaffolded searchform Link to this post

    Hi,
    I'm currently working with a scaffolded searchform and need to modify the generated query (ss 2.4b2).
    The basic situation is:
    I've got a list of entries with an expiry date - initially I show all entries with expiry dates larger or equal then today ( "( ExpiryDate >= DATE( NOW() ) )" ). But when searching, the query is built from the defined search fields/filters. Concerning those, an equal or greater than filter is missing ;-)
    My problem is: How can I tell the query to add another filter like "ExpiryDarte" >= DATE( NOW() ) or something similar or even alter the query manually?

    Regards,
    Marc

  • Double-A-Ron
    Avatar
    Community Member
    603 Posts

    Re: Problem with search and scaffolded searchform Link to this post

    Hi mate.

    I did something similar to this for removing searches through PDF's and Word docs in the Assets directory. It's more removing results matching certain criteria rather than ignoring them during the search. Probably not the most effient way, but it works. Where is my results code. Check out the foreach loop.

    public function results($data, $form)
    {

    $results = $form->getResults();

    foreach($results AS $result) {
    if($result->ClassName == "File") $results->remove($result);
    }

    $data = array(
    'Results' => $form->getResults(),
    'Query' => $form->getSearchQuery(),
    'Title' => 'Search Results'
    );

    return $this->customise($data)->renderWith(array('ContentPage', 'Page'));
    }

    So you could theoritically run a comparison on any field and remove it from the results. E.G.

    if($result->LastEdited == "2010/03/06 12:00:00") $results->remove($result);

    I haven't tried this, and not sure about custom page types with custom fields. The query runs on the SiteTree_Live table as far as I know, so you may only have access to those fields.

    The only other thing I can think of is creating a custom object us DataObject::get() and making sure your result array ($data in the above code) is in the same format/structure. Definately do-able. That way you can bypass the default methods and customize the query as much as you like.

    Aaron

  • Euphemismus
    Avatar
    Community Member
    82 Posts

    Re: Problem with search and scaffolded searchform Link to this post

    Hi Aaron,

    thank you! I've tried a lot of things and found another way around ;-)
    In my special case with the ExpiryDate it was possible to have a GreaterThanFilter on a hidden "ExpiryDate" field and after creating the scaffolded search form I did this:

    // workaround for presetted searchfields
    $expiryDateYesterday = date( "d.m.Y", mktime( 0, 0, 0, date( "m" ), date( "d" )-1, date( "Y" ) ) );
    $objExpiryDate = new HiddenField( 'ExpiryDate', 'ExpiryDate', $expiryDateYesterday );
    $fields->replaceField( 'ExpiryDate', $objExpiryDate );

    I think this is a bite more efficient than removing results from an already generated resultset.

    Regards,
    Marc

  • Double-A-Ron
    Avatar
    Community Member
    603 Posts

    Re: Problem with search and scaffolded searchform Link to this post

    That looks like a cool solution Marc.

    So did you put that in your form generator? What did you need to change on your results() method?

    Aaron

  • Euphemismus
    Avatar
    Community Member
    82 Posts

    Re: Problem with search and scaffolded searchform Link to this post

    Hi Aaron,

    thanks
    I didn't have to modify the results() method. The only thing I did was:

    public function getCustomSearchContext()
    {
    $fields = $this->scaffoldSearchFields( array(
    'restrictFields' => array(
    'Title',
    'Content',
    'Instrument',
    'Plz',
    'Location',
    'Ambition',
    'ExpiryDate',
    'EntryCategoryID',
    ),
    'fieldClasses' => array(
    'ExpiryDate' => 'HiddenField',
    )
    )
    );

    $filters = array(
    'Title' => new PartialMatchFilter( 'Title' ),
    'Content' => new PartialMatchFilter( 'Content' ),
    'Instrument' => new ExactMatchFilter( 'Instrument' ),
    'Plz' => new PartialMatchFilter( 'Plz' ),
    'Location' => new ExactMatchFilter( 'Location' ),
    'Ambition' => new ExactMatchFilter( 'Ambition' ),
    'ExpiryDate' => new GreaterThanFilter( 'ExpiryDate' ),
    'EntryCategoryID' => new ExactMatchFilter( 'EntryCategoryID' ),
    );

    $expiryDateYesterday = date( "d.m.Y", mktime( 0, 0, 0, date( "m" ), date( "d" )-1, date( "Y" ) ) );
    $objExpiryDate = new HiddenField( 'ExpiryDate', 'ExpiryDate', $expiryDateYesterday );
    $fields->replaceField( 'ExpiryDate', $objExpiryDate );

    return new SearchContext(
    $this->class,
    $fields,
    $filters
    );
    }

    Initially on the controller I do:

    public function ActiveEntries()
    {
    return $this->Entries(
    "( ExpiryDate >= DATE( NOW() ) )"
    );
    }

    This gives me a reduced resultset initially. Since the searchContext doesn't work like this, I had to do it ugly with the hidden field within the model where the CustomSearchContext is defined

    Edit: It woud be really nice to have some more possibilities like presetting values in a i.e. fieldsPreset = array( 'fieldname' => 'value' ) or something like that. Also the the filters are lacking >= and <=
    Plus there needs to be a possibility to restrict the resultset otherwise, too. Like with an addition WHERE statement.
    This might be a nice candidate for a changerequest ;-)

  • javelin
    Avatar
    Community Member
    12 Posts

    Re: Problem with search and scaffolded searchform Link to this post

    Thank you Aaron and Marc! This solved two problems for me at once. I needed to restrict searches on a specific page to only dataobjects related to that page (has_many) and at the same time offer the possibility of equal-to-or-greater-than date-search.

    Both your approaches solved this for me at once:

    This was my code for filtering only related dataobjects:

    $context = singleton('Apartment')->getDefaultSearchContext();
    $results = $context->getResults($data);
    //Filter out any apartments not related to this page.
    foreach($results AS $result) {
       if($result->ApartmentListID != $this->ID) $results->remove($result);
    }
          
    return $this->customise(array('Results' => $results))->renderWith('ApartmentList_results');

    Thank you again!

  • Euphemismus
    Avatar
    Community Member
    82 Posts

    Re: Problem with search and scaffolded searchform Link to this post

    Hi
    Yo could also do the filtering while searching if you modify the searchform like with the ID field.
    -> push a new hidden field into the searchform and do a ExactMatchFilter on the ID.
    This will significantly reduce your costs when searching large heaps of data.
    The solution with iterating the whole resultset and removing entries could get slow.

    Regards,
    Marc

  • Double-A-Ron
    Avatar
    Community Member
    603 Posts

    Re: Problem with search and scaffolded searchform Link to this post

    I agree with Marc, his method is alot more efficient in the long term, especially if you end up adding alot of Pages to your site. The method I posted (and you used) will pull even objects you don't need, then remove them.

    Makes sense to ignore those redundant records right from the start.

    Aaron

    2524 Views
Page: 1 2
Go to Top

Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com

Comments on this website? Please give feedback.