I've been searching the web and rattling my brain for weeks but to no avail.
I have a product database on WordPress (v3.4) and I am trying to make it searchable using URL queries.
Ideally this is the scenario I want:
- domain/products - to show all of the products
- domain/products?tax1=term1 - to filter the products by a taxonomy
- domain/products?tax1=term1&tax2=term2 - to filter my multiple
taxonomies.
The post_type is called 'product' and I currently have a page called products with a page-template assigned to it. However, whenever I try to use the WordPress URL queries is redirects me to a similar URL'd news post (e.g. domain/2011/10/01/products-are-cool).
How do I go about creating these filters and having them display the results correctly?
UPDATE: I've come up with a solution that works perfectly for me.
if(isset($_GET)) $options = $_GET;
if (!empty($options)) {
$posts = new WP_Query( array(
'post_type' => 'product',
'orderby' => 'title',
'order' => 'asc',
'paged' => $paged,
'tax1' => $options['tax1'],
'tax2' => $options['tax2'],
));
And then use add_query_arg($termslug,$term->slug)
to append the taxonomies onto the URL.
You has some conflicting URI structure rules. You can add a line to htaccess to solve that for this particular page. Place it before the WordPress generated rules but after the RewriteEngine On
clause.
RewriteRule /products /?page=33 [L,QSA]
Where obviously 33 is the page id. The [L] directive means this is the last rewrite to be performed and should go straight to the new URI. [QSA] should attach any query that products?had=here
to the new URI ?page=33&had=here
.
I would point out the difference between Redirect
and Rewrite
:
Basically the solution I suggested shows the visitor/ browser the /products?tax=tax1
address while showing WordPress the rewritten address /?page=33&tax=tax1
.
Doing this in the .htaccess
before other WordPress rewrites take place and using [L] which stops the execution of any following rewrites, allows you to avoid WordPress' internal mechanism of analyzing the URIs.
WordPress' internal mechanism would have tried to find out which category/ page/ post the URI is pointing to. But your URI scheme is not optimal (if you have categories and pages with the same name WordPress will choose one of them not necessarily the right one).
The following function needs to be put in the functions.php of your template code. Or in a plugin.
function custom_search_query( $request ) {
$query = new WP_Query(); // the query isn't run if we don't pass any query vars
$query->parse_query($request);
$request['post_type'] = 'product';
// this is the actual manipulation; do whatever you need here
if(isset($_GET))
$options = $_GET;
if (!empty($options)) {
$i = 0;
$request['tax_query'] = array(); // resetting any previously selected meta_queries that might "linger" and cause weird behaviour.
// CAREFUL HERE ^ might not be desired behaviour
foreach($options AS $key => $value) {
$request['tax_query'][$i]['taxonomy'] = $key;
$request['tax_query'][$i]['terms'] = array($value);
$request['tax_query'][$i]['operator'] = 'IN';
$i++;
}
}
return($request);
}
add_filter( 'request', 'custom_search_query' );
It makes no validation on the user input, (wordpress might do some of that but it's better if you do it).