Jump to content
Sign in to follow this  
jds43

GET search with filter

Recommended Posts

Hello,

I have a search page loosely based on Skyscrapers where I'm parsing a selector with options 'beds', 'bathrooms', 'size' fields. It is working well until I select 'Any' after I've run a search. This is where no results are returned (/?beds=&bathrooms=&size=&submit=). I want it to reset and show all results.

I hope this isn't too vague.

 

Share this post


Link to post
Share on other sites

Is "any" an actual form item (checkbox, radio button...) ? If it was, then you would see it in the query parameters as well (e.g. /?beds=&bathrooms=&size=&any=1&submit=), and could easily add it to your selector query logic.

If "any" just means that neither beds, bathrooms nor size was selected by the user (which your posted GET example suggests), you would have to account for that scenario, and check for the absence of parameters, and thus send another search selector to PW.

11 minutes ago, jds43 said:

I hope this isn't too vague.

If you could post the relevant code, it would sure help.

Share this post


Link to post
Share on other sites

Thanks @dragan

'Any' has no value at this point. I just need it as a default selection that would allow all to display.

<form class="uk-form uk-padding-large" method="get" action="<?= $page->url; ?>">

        <h4 class="uk-h3">Filter Results:</h4>
        <a class='uk-text-uppercase' href='<?= $page->url; ?>'>Reset Filter</a>
        		
		<div class="uk-grid uk-grid-small uk-flex-bottom uk-margin-top uk-child-width-1-1 uk-child-width-1-2@s uk-child-width-1-4@m">

			<div class="">
				<label class="uk-form-label" for="search-bedrooms">Bedrooms</label>
				<div class="uk-form-controls">
					<select id="search-bedrooms" name="beds" class="uk-select uk-form-width-large" tabindex="1">
						<option value="">Any</option>
                        <?php
							// generate a range of bedrooms, checking our whitelist to see if any are already selected
							foreach(array('2', '3', '4') as $range) {
								$selected = $range == $input->beds ? " selected='selected'" : '';
								echo "<option$selected value='$range'>$range</option>";
							}    
                        ?>						
                    </select>
				</div>	
			</div>	
			<div class="">
				<label class="uk-form-label" for="search-baths">Bathrooms</label>
				<div class="uk-form-controls">
					<select id="search-baths" name="bathrooms" class="uk-select uk-form-width-large" tabindex="2">
						<option value="">Any</option>
                        <?php
							// generate a range of bathrooms, checking our whitelist to see if any are already selected
							foreach(array('1.5', '2.0', '2.5', '3.0') as $amount) {
								$selected = $amount == $input->bathrooms ? " selected='selected'" : '';
								echo "<option$selected value='$amount'>$amount</option>";
							}    
                        ?>					
			        </select>
				</div>	
			</div>	
			<div class="">
				<label class="uk-form-label" for="search-size">Square Footage</label>
				<div class="uk-form-controls">
					<select id="search-size" name="size" class="uk-select uk-form-width-large" tabindex="3">
						<option value="">Any</option>
                        <?php
							// generate a range of sq ft, checking our whitelist to see if any are already selected
							foreach(array('1,000-1,250', '1,251-1,500', '1,501-1,750', '1,751-2,000', '2,000+') as $range) {
								$selected = str_replace(',', '', $range) == str_replace(',', '', $input->size) ? " selected='selected'" : '';
								echo "<option$selected value='".str_replace(',', '', $range)."'>$range</option>";
							}    
                        ?>						
			        </select>
				</div>
			</div>
			<div id="view-sibling" class="uk-visible@s">
			<?php
    			$not_this = $page->siblings("limit=1", false);
    			foreach($not_this as $not) {
                    echo "<a href='$not->url' class='uk-button grey-button uk-width-expand'>View $not->title Collection&nbsp;<i class='fa fa-chevron-right'></i></a>";
                }
            ?>
			</div>
		</div>
		
		<div class="uk-grid uk-grid-small uk-flex-bottom uk-margin-top uk-child-width-1-1 uk-child-width-1-2@s uk-child-width-1-4@m">	
    		<div class="">
    			<button type="submit" id="search-submit" class="uk-button gold-button uk-width-expand" name="submit" tabindex="4">Search</button>
    		</div>
		</div>

	</form>
                foreach(array('beds', 'bathrooms', 'size') as $key) {
                
                	if(!$value = $input->get($key)) continue; 
                	
                	// see if the value is given as a range (i.e. two numbers separated by a dash)
                	if(strpos($value, '-') !== false) {
                		list($min, $max) = explode('-', $value); 
                		$min = (int) $min;	
                		$max = (int) $max; 
                		$selector .= "$key>=$min, $key<=$max, ";
                		//$summary[$key] = (substr($max, 0, 3) == '999') ? "$min and above" : "$min to $max";
                		$input->whitelist($key, "$min-$max"); 

                	// see if the value is given as a float (i.e. decimal, this is specific to bathrooms)
                    } else if(strpos($value, '.') !== false) {
                        $value = $sanitizer->selectorValue($input->get->bathrooms);
                        $selector .= "bathrooms%=$value, "; 
                        $input->whitelist($selector, $value); 
    				
                	// see if the value ends with a +, which we used to indicate 'greater than or equal to'
                	} else if(substr($value, -1) == '+') { 
                		$value = (int) $value; 
                		$selector .= "$key>=$value, ";
                		//$summary[$key] = "$value and above";
                		$input->whitelist($key, "$value+"); 
	
                	} else {	
                		$value = (int) $value; 
                		$selector .= "$key=$value, ";
                		//$summary[$key] = $value;
                		$input->whitelist($key, $value); 
                	}
                }

 

Share this post


Link to post
Share on other sites

Well, the first thing you should do is change

<option value="">Any</option>

to something like

<option value="any">Any</option>

Then you would at least get a parameter in PW that you could act upon.

Before you run your
foreach(array('beds', 'bathrooms', 'size') as $key) {
routine, I would check if all of those three parameters are set to "any" (or whatever you choose to use), and if that's the case, skip the entire foreach() and go straight to the "full search".

  • Like 1

Share this post


Link to post
Share on other sites

Okay, I'm also using the code below that comes after the foreach:

				// did we find any matches?
				if(count($input->get)) {										
	    			// Find pages that match the selector
    				$results = $pages->find($selector);
    				if(count($results) > 0) {
                        $message .= "<h3 class='uk-h5'>There are <strong>".count($results)."</strong> House Plans</h3>";
                    } else {
                        $message .= "<h3 class='uk-h5'>Sorry, no results</h3>";   
                    }
                } else {
                    $results = $page->children();
                }

I tried checking the three parameters in a conditional like: if($input->get('beds') == 0 || ($input->get('bathrooms') == 0 || ($input->get('size') == 0 || ). But couldn't really make it work. I ended up modifying the code above to:

				// did we find any matches?
				if(count($input->get)) {										
	    			// Find pages that match the selector
    				$results = $pages->find($selector);
    				if(count($results) === 0) {
                        $results = $pages->find('template=house-plan');
                    }
                } else {
                    $results = $page->children();
                }
                
                echo "<h3 class='uk-h5'>There are <strong>".count($results)."</strong> House Plans</h3>";

So, the result is a query string (/?beds=0&bathrooms=0&size=0&submit=1) with all select options set to 'Any' directly after a search has been performed. I suppose this is acceptable, but wish I could remove it. Thank you @dragan for the help.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By michelangelo
      Hello guys, I am building a sort of an archive. Relatively simple, although I have about 8000 records, each with 15 fields (text, int, images, url). I created a crude search system with a form (emulating the famous Skyscrapper example) to filter through the system. Everything works but it is quite slow... I have 2 questions which are related:

      1. How can I search through the database?
      2. What is a good practice to display many records like these?
      -----------------------------------------
      1. I am retrieving the results with
      $songs = $pages->findMany('template=nk-song'); Then I do a foreach to render them all. I am unsure if that is a good way. If I render all of them on the page, it creates thousands of divs with a bit of text, and this can take a while (10s-15s).
       
      2. This one is even worse :D as every time I retrieve my desired records with something like this:
      $page->find("field_to_search_through~=my_query_string") I get between 20 and 200, but when I render them I am creating iframes with YouTube videos and that can take up to 10s to finish. I "solved" it by only loading the iframes if they are in view with IntersectionObserver on the client-side. But I feel there is a more precise PHP / ProcessWire approach.
       
      Just to clarify, I started doing all of this custom rendering and querying because tools like ElasticSearch or SearchEngine were a bit complicated and I needed a simple to retrieve information and then display it in my own way.
      Thank you!
    • By snobjorn
      I have a website with multiple content types that I want to be accessible through search. I really like the live search on processwire.com, that sorts content types while typing. I tried to find the code to recreate this, with no luck. Does anyone know if this is jquery, specific jquery plugins, json/xml cached files, and what kind of PHP code is used? Any tip that point me in the right direction would be much apperciated.
      The search result listing seems fairly easy to create with sorting through parameters.
    • By Greg Lumley
      Hi! In busy learning to know PW better I'm looking at existing code.
      I have Bitpoets Editorial Responsive Blog as example. While looking through the code I've just found this line in the blog-head.php 
      <link rel="stylesheet" href="<?= $config->urls->templates ?>assets/css/main.css?ts=<?= time() ?>" /> I hope it's not a stupid question but I've never seen this before...
      main.css?ts=<?= time() ?> I notice the main template is empty but of course renders on the front end.
      Using a timestamp really has me totally confused. Can someone explain it to me please. 
      Thank you! 
      Greg
    • By Anders
      I want to allow full text search on my site. There is a very nice solution that comes right out of the box:
      $selector = "title|body~=$q, limit=50"; This works, but to make it even better I would want to give higher weight to pages where the search term occurs in the title, than if it just occurs in the body. After all, a page with the title "Wine from France" is probably the best match for the search "france wine". How do I accomplish this in ProcessWire?
      I can see three possible paths, but I am not very fond of any of them:
      Do a direct SQL query, circumventing the API, along these lines. But I would prefer to abstract away the database layout if at all possible. Use something like ElasticSearch, but to be honest that would be to complicated to set up and maintain in the long run. Make multiple lookups, first for matches in the title, then for matches in the body, and merge and sort in PHP. My suspicion is that this would get complicated quite quickly. For instance, how do you deal with a page that has two of the three search terms in the title and the third in the body? Is there a magic option four I should look into? Or are any of the above options better than the others? Any input is welcome!
    • By brdje
      Greetings,
       
      I've created a product database which all use the template product.php and are published on the website.
      I'm trying to create an overview table with pagination of all the products, but using $pages->get does not return an object, only the object title.
      $products = $pages->get("template=product, limit=10"); This returns 10 strings in the frontend but not the object. When looping over the result set to get product fields, i get the following error:
      Notice: Trying to get property 'title' of non-object
       
      Because the product database is fairly large, i've added a pagination using the same query and this does return all the pages, but i can't click on the links that the paginator renders.
      $results = $pages->find("template=product, limit=10"); if($results->getTotal() > 10) { echo $results->renderPager(array( "nextItemLabel" => "Volgende", "previousItemLabel" => "Vorige", "currentItemClass" => 'active' )); }
      I've added the option in the template to allow page numbers. When i navigate to the link manually, i still end up seeing the 10 first products.
       
      I've tried changing several settings around, but i'm a bit stuck on how to resolve these issues. Do you have any advice what I need to adjust?
      Thanks in advance for your feedback.
       
       
×
×
  • Create New...