Jump to content
nikola

Search form with multiple fields

Recommended Posts

I have a small search form that searches products by selected manufacturer, price or manufacturer and price combined.

Manufacturer is a page list field, and the generated prices are a range.

This is the form:


<label for="search-manufacturer">Manufacturer</label>

<select id="search-manufacturer" name="manufacturer">
<option value="">Any</option>
<!--?php
foreach($pages--->get("/manufacturer/")->children() as $manufacturer) {
$selected = $manufacturer->name == $input->whitelist->manufacturer ? " selected='selected' " : '';
echo "{$manufacturer->title}";
}
?>
</select>

<label for="search-price">Price</label>

<select id="search-price" name="price">
<option value="">Any</option>
<!--?php
foreach(array('0-50', '50-250', '250-500', '500-750', '750-1000', '1000+') as $price) {
$selected = $price == $input--->whitelist->price ? " selected='selected'" : '';
echo "$price";
}
?>
</select>

<input type="submit" id="search-submit" name="submit" value="Search">

What code do I need to put into "manufacturer-search" template to search products by criterions mentioned above?

I've looked into the skyscapers profile but couldn't make it work...

Thanks

Share this post


Link to post
Share on other sites

I'm not sure there's enough to go on here to say for sure. Where are you setting the $input->whitelist values? That's probably the same place where you want to build your search selector. Something like this:

$selector = 'parent=/products/, ';

$name = $sanitizer->pageName($input->get->manufacturer);
$man = $pages->get("parent=/manufacturer/, name=$name");
if($man->id) {
$input->whitelist('manufacturer', $man->name);
$selector .= "manufacturer=$man, ";
}

list($priceMin, $priceMax) = explode('-', $input->get->price);
$priceMin = (int) $priceMin;
$priceMax = (int) $priceMax;
if(!$priceMax) $priceMax = 99999; // or some other max value
$input->whitelist('price', "$priceMin-$priceMax");
$selector .= "price>=$priceMin, price<=$priceMax, ";

$selector .= 'limit=25';
$products = $pages->find($selector);

if(count($products)) echo $products->render();
else echo "<h2>Sorry no products found</h2>";

Share this post


Link to post
Share on other sites

Ryan, thanks for the exapmle.

It's working fine with manufacturer if I remove code block from selector:

list($priceMin, $priceMax) = explode('-', $input->get->price);
$priceMin = (int) $priceMin;
$priceMax = (int) $priceMax;
if(!$priceMax) $priceMax = 99999; // or some other max value
$input->whitelist('price', "$priceMin-$priceMax");
$selector .= "price>=$priceMin, $price<=$priceMax, ";

If I include this block of code PW throws me an error:

PHP Notice: Undefined offset: 1 in C:\inetpub\wwwroot\pw\site\templates\manufacturer-search.php on line 13 PHP Notice: Array to string conversion in C:\inetpub\wwwroot\pw\site\templates\manufacturer-search.php on line 18 PHP Fatal error: Exception: Field does not exist: Array (in C:\inetpub\wwwroot\pw\wire\core\PageFinder.php line 244)

manufacturer-search.php template consist only of code you posted above.

Share this post


Link to post
Share on other sites

nikola, the problem is probably here:

$selector .= "price>=$priceMin, $price<=$priceMax, ";

should probably be:

$selector .= "price>=$priceMin, price<=$priceMax, ";

(notice the dollar sign in the second condition)

  • Like 1

Share this post


Link to post
Share on other sites

Thanks Adam, I completely overlooked that, it's working fine now. :)

Share this post


Link to post
Share on other sites

Sorry for the typo, I've corrected my original post. Thanks for finding it Adam.

Share this post


Link to post
Share on other sites

Hi! Search realization is impossible to me, prompt as it is possible to solve it if the form with selectors at me looks so:

<form id="city_obj_search" method="get" action="<?php echo $config->urls->root?>city_obj_search/">
<ul>
<li>
<?php
foreach($pages->get("/business_type/")->children() as $type_of_oper) {
$checked = $type_of_oper->name == $input->whitelist->type_of_oper ? " checked='checked' " : '';
echo "<div>
<label>
<input$checked type='checkbox' name='type_of_oper' value='{$type_of_oper->name}'>{$type_of_oper->title}
</label>
</div>" ;
}
?>
</li>
<li>
<label for="district_location">District</label>
<select id="district_location" name="distr">
<option value="any">Any</option>
<?php
foreach($pages->get("/district/")->children() as $distr) {
$selected = $distr->name == $input->whitelist->distr ? " selected='selected' " : '';
echo "<option$selected value='{$distr->name}'>{$distr->title}</option>";
}
?>
</select>
</li>
<li>
<label for="subway_station">Subway station</label>
<select id="subway_station" name="subway">
<option value="any">Any</option>
<?php
foreach($pages->get("/subway_station/")->children() as $subway) {
$selected = $subway->name == $input->whitelist->subway ? " selected='selected' " : '';
echo "<option$selected value='{$subway->name}'>{$subway->title}</option>";
}
?>
</select>
</li>
<li>
<label for="object_cost_ru">Cost in ru</label>
<select id="object_cost_ru" name="costru">
<option value="any">Any</option>
<?php
foreach(array('30000-50000', '50000-100000', '100000-250000', '250000-500000', '500000-1000000', '1000000+') as $costru) {
$selected = $costru == $input->whitelist->costru ? " selected='selected'" : '';
echo "<option$selected value='$costru'>$costru руб.</option>";
}
?>
</select>
</li>
<li>
<label for="object_cost_dol">Cost in dollars</label>
<select id="object_cost_dol" name="costdol">
<option value="any">Any</option>
<?php
foreach(array('1000-3000', '3000-10000', '10000-20000', '20000-30000', '30000+') as $costdol) {
$selected = $costdol == $input->whitelist->costdol ? " selected='selected'" : '';
echo "<option$selected value='$costdol'>$costdol $</option>";
}
?>
</select>
</li>
<li>
<label for='search_id'>ID</label>
<input type="text" placeholder="00000" name="id" id="search_id" value="<?php
if($input->whitelist->id) echo htmlentities($input->whitelist->id, ENT_QUOTES); ?>" />
</li>
<li>
<input type="submit" id="search_submit" name="submit" value="Find!">
</li>
</ul>
</form>

I wish that this request would be processed the search page «city_obj_search/», but the information from the forum (http://processwire.c...op-down-search/) that I use does not help me either an error or an empty result. Help to understand, please.

Share this post


Link to post
Share on other sites

I'm not sure I understand the question 100%, but I think we need to take a look at the code that actually generates the selector (rather than just the code that generates the form). Also, while developing search engines, I always find it helpful to output the selector that is being used. Once the site is finished with the development then I remove it. But to do this, you may want to add something like this at the top of your search results:

<?php echo "<h2>" . htmlentities($selector, ENT_QUOTES, "UTF-8") . "</h2>"; ?>

Share this post


Link to post
Share on other sites

Thanks for the reply Ryan and code, it clarifies some things )

Question that I asked - I solved (so delete it) and walked right up to the search, the results of which I can not get it.

Form code I've described above, in a search template I use the following code (searching only two fields participate now):

include("./header.inc");
$selector = 'parent=/direction/city/, ';
if($input->get->id) {
	$value = $sanitizer->selectorValue($input->get->id);
	$selector .= "object_id~=$value, ";
	$input->whitelist('id', $value);
}
if($input->get->distr) {
	$distr = $pages->get("/district/" . $sanitizer->pageName($input->get->distr));
	if($distr) {
	$selector .= "parent=$distr, ";
	$input->whitelist('distr', $distr->name);
	}
}
$objects = $pages->find($selector);
$count = count($objects);
echo "<h2>" . htmlentities($selector, ENT_QUOTES, "UTF-8") . "</h2>";
if($count) {
echo "<h2>Found pages: $count</h2>";
foreach($objects as $obj) {
echo "<div><a href='{$obj->url}'>{$obj->title}</a></div>" ;
}
} else echo "<h2>There are no results matching the query</h2>";
include("./footer.inc");

I made them for example, but they do not work, and the reason that I can not yet understand.

upd:

Slowly I begin to understand the structure.

It appears in the search involved a hierarchy of pages. On an example of skyscrapers it: cities -> city -> object -> its properties (height, floors, year).

What if such structure isn't present and my objects aren't enclosed, and are parallel?

What role does this value $selector = 'parent=/direction/city/, '; ?

Differently: how add in search of architects of skyscrapers? )

Edited by AlexV

Share this post


Link to post
Share on other sites

AlexV, what was the output of your $selector (in the <h2>?). The code looks good to me, but I don't know the full site structure either, so don't necessarily have the context to relate it to that.

Share this post


Link to post
Share on other sites

Ryan, when I remove the code

/*if($input->get->distr) {
	$district = $pages->get("/district/" . $sanitizer->pageName($input->get->distr));
	if($district) {
			$selector .= "parent=$district, ";
			$input->whitelist('distr', $distr->name);
	}
}*/

rest of the code begins to work.

When I turn on, I get:

parent=/direction/city/, parent=1253,

There are no results matching the query

I can guess why. Here is the hierarchy of pages:

|- direction

| |

| |- city

| |- object 1 (object has a Pagefield named «district», in which selected pages «district 1 and so on»)

| |- object 2

| |- and so on

|

|- district

| |- district 1

| |- district 2

I want to get a list of objects from the section «city» criteria «district». How can I do?

upd:

I found the solution, it was too easy, instead of the «parent» it is necessary to use a «field»

$selector .= "parent district_location=$district, ";

But now another question, not displayed «whitelist» )

In what may be the reason?

upd2:

I found the solution works until I add another criterion in the search, for example:

if($input->get->type_of_oper) {
	$type_of_oper = $pages->get("/business_type/" . $sanitizer->pageName($input->get->type_of_oper));
	if($type_of_oper) {
			$selector .= "type_of_operation=$type_of_oper, ";
			$input->whitelist('type_of_oper', $type_of_oper->name);
	}
}

after adding it, I get:

parent=/direction/city/, district_location=, type_of_operation=1021,

how to avoid it?

Edited by AlexV

Share this post


Link to post
Share on other sites

$pages->get() will always return a Page object, so rather than doing this:

if($type_of_oper) {

you should do this:

if($type_of_oper->id) {

When a $pages->get() doesn't match anything, it returns a NullPage. The easiest way to check for a NullPage is by seeing if it has an id, like above. Though you could also do this if you preferred:

$p = $pages->get($selector); 
if($p instanceof NullPage) {
  // no page found
} else {
  // page found
}
  • Like 1

Share this post


Link to post
Share on other sites

There are still questions of search. While I can't answer them itself.

First question. Now I have two checkbox, it work by a principle "or", in what case they will work as "and". Now the code in the search template looks like this:

$name = $sanitizer->pageName($input->get->type_of_oper);
$man = $pages->get("parent=/business_type/, name=$name");
if($man->id) {
       $input->whitelist('type_of_oper', $man->name);
       $selector .= "type_of_operation=$man, ";
}

Second question. In the search form has two text fields "from" and "before". How to realize search for them?

Сode search form:

<label for="square">Square</label>
<input type="text" name="squareMin" value="<?php if($input->whitelist->squareMin) echo htmlentities($input->whitelist->squareMin, ENT_QUOTES, "UTF-8"); ?>" />
<input type="text" name="squareMax" value="<?php if($input->whitelist->squareMax) echo htmlentities($input->whitelist->squareMax, ENT_QUOTES, "UTF-8"); ?>" />

Code that I tried to use in search template, but it does not work:

$valueMin = $sanitizer->selectorValue($input->get->squareMin);
$valueMax = $sanitizer->selectorValue($input->get->squareMax);
$selector .= "object_square>=$valueMin, object_square<=$valueMax, ";

Share this post


Link to post
Share on other sites

I think that your first example looks fine in terms of the code. I'm not sure I understand the question on that one.

For the second one, what kind of field is object_square? I don't see anything amiss in your code, but based on the operators ">=" and "<=" it makes me think that object_square is an integer and should probably be sanitized/typecast as such, rather than as a string. i.e.

$valueMin = (int) $input->get->squareMin; 

Also there's no reason to run an integer through htmlentities(). There's also no harm in it, but just wanted to mention it might not be necessary if you are keeping it as an integer.

Share this post


Link to post
Share on other sites

Thanks for the reply Ryan!

In the second case, I used a «text» field, so that did not work. I changed it on the field «float» and added your code, thank you, it works!

I will describe in more detail the first question.

I have two checkboxes and code which I specified above.

Now when I choose one checkbox search works well. When I choose two checkboxes, search shows that one is chosen only. How it is possible to change a code that search was on two values (which I select checkboxes)?

Share this post


Link to post
Share on other sites

It's hard to answer for sure, because I don't see anything in your first code example that draws a relation to multiple checkboxes on the front-end. But based on what you've said, I'm guessing one of the checkboxes has a name of "type_of_oper"? i.e.

<input type='checkbox' name='type_of_oper' value='something' />

If there is another checkbox, then you would need some code to handle that one too. Since these are checkboxes rather than radio buttons, you'll want to give each one a different name in their <input> tag. You could also take an array approach, using the same name and appending "[]" to it so that they come through as an array. But if we're only talking about 2 checkboxes here, then I think it's better to just make them separate.

Share this post


Link to post
Share on other sites

Thanks Ryan! I understood your idea. I yet don't know as it to realize, but I will try )

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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By a.masca
      Goodmorning everyone,
      sorry for the inconvenience but I have a problem that I can't find in any other post.
      Strange things happen on a site:
      - despite everything being configured correctly (as already done in dozens of other sites) only superusers can create new pages
      - if I insert in a selector "include = all" the result is always 0
      - I should restore a series of pages incorrectly inserted in the trash, but I cannot select them with the selector "status = Trash"
      Some idea?
      Thanks so much for your valuable support.
    • By LAPS
      According to this old post, I'm trying to use the PW cache feature:
      $my_page = $pages->get($pageId); if($my_page->viewable()) { $content = $cache->get("my_page"); if(!$content) { $content = renderCustom($my_page->children); $cache->save('my_page', $content, 3600); } echo $content; } function renderCustom(PageArray $items) { foreach($items as $item) { echo $item->title; // ... heavy content loading } } After loading the page which renders the above code, in the admin I can see something was cached (note: I'm using ClearCacheAdmin) :

      But when I reload the page the cached value seems do not be used and the page loads slowly.
      The result of doing var_dump() is the following:
      var_dump($cache); // return object(ProcessWire\WireCache)#20 (0) { } $content = $cache->get("my_page"); var_dump($content); // return string(0) ""  
      What could be the problem?
    • By LAPS
      Can you confirm that the function renderField for fieldset fields, even having the file /site/templates/fields/fieldName.php or /site/templates/fields/fieldName/$file.php (using $file argument), does not render anything as expected?
      $page->renderField('fieldsetName') // returns nothing ... or am I wrong on something?
    • By LAPS
      Hi there,
      I'm working on an email message template and would like to render a custom one to be sent.
      I tried to use $files->render() this way
      // rendering file e.g. a template file or a hook statement in ready.php $body = $files->render('emails/myfile', array( 'myVar1' => $var1, 'myVar2' => $var2, ... )); but $vars seems to be not accessible from within the rendered file. That is, $vars seems to be not set:
      // rendered file emails/myfile.php $myVar1 = $vars['myVar1']; // is not set $myVar2 = $vars['myVar2']; // is not set ... // is not set How can I get the $vars so to properly render the custom message template for sending the email?
       
      Notes:
      By using $files->include() the $vars is accessible but I cannot use this method because I should retrieve the output $body as a return value for sending the email later. So, I'm still looking to render the custom message using $files->render(). This thread is someway related to this one.
    • By Markus (Blue Tomato)
      I'am working on a migration script from the ImageExtra Module to the new Custom Image Fields feature in ProcessWire.
      I have some problems while setting a field value to the new custom image field. I have set up the custom field and it works correct in the admin panel but not via the API:
      $page->images->my_custom_image_field = "test"; $page->save(); Results into:
      Fatal error: Uncaught ProcessWire\WireException: Item 'my_custom_image_field' set to ProcessWire\Pageimages is not an allowed type in /var/www/html/wire/core/WireArray.php:458
       
       
×
×
  • Create New...