When I used an exposed filter the filter selection is passed as name/value pair in the url, for example:
members?field_a=valuea&field_b=valueb
How can I set it up to use more of a "pathauto" style url:
members/valuea/valueb
Drupal Answers is a question and answer site for Drupal developers and administrators. It only takes a minute to sign up.
Sign up to join this communityWhen I used an exposed filter the filter selection is passed as name/value pair in the url, for example:
members?field_a=valuea&field_b=valueb
How can I set it up to use more of a "pathauto" style url:
members/valuea/valueb
A colleague of mine created a module called path data a while back. His intentition was to solve this very problem. Unfortunately it has turned out that it conflicts with regular path aliases, so it will work on a site like drupal.org that doesn't use aliases, but will break links on a path-alias using site.
Currently, it's my belief that the only generic way to solve this issue is either manipulating the URLs at the httpd layer, or using hook_url_inbound_alter and hook_url_outbound_alter. You can read a bit more about the mentioned hooks at this question.
However, if I were to give this another shoot myself, I would attempt a Views specific solution instead, as this problem is common enough that it could be justified to have a module for this.
In hook_views_pre_build, one could take data from a url like "members/valuea/valueb", push these values into $_GET['q'], let views build it's query seeing the get arguments "in the url", then possibly remove them again in hook_views_post_build.
There is a module, Query Parameters To URL, that I recently released that addresses the issue you are describing:
This module provides the ability to rewrite URL query parameters into Clean URL components on specified paths.
You can configure which paths should have their query arguments rewritten as clean URL components using a simple regular expression, or by implementing a module hook.
That way you can transform a Views exposed filter URL like
http://example-site.com/events?field_category_id[0]=100&field_category_id1=101&field_author_name[0]=John&field_author_surname[0]=Doe
Underneath it uses hook_url_inbound_alter, hook_url_outbound_alter, and hook_init with redirects where necessary.
Exposed filters are forms, which means that the place where they are redirecting ("action" attribute), needs to be known before user will choose any option. So we cannot redirect him to any pretty URL that contains information about his choice. The workarounds:
JavaScript. Use JavaScript to alter on the fly "action" attribute of exposed filter form based on options that user chose, and set "action" to URL of proper view with proper contextual filters configured. But I doubt it would be "SEO friendly" then (please someone correct me if I'm wrong).
Do double redirect. By using hook_form_alter, after getting the form, redirect user to url of proper view, with proper contextual filters configured, based on his input. This may actually need a user confirmation on some browsers, so it may be extremely annoying.
In both above methods, you would need to use https://drupal.org/project/views_expost to change method of those forms to POST, so variables won't pollute users URL.
The bottom line is that if you need to have pretty urls with exposed filters - you are probably doing something wrong. Because I think they are just for filtering data, and should not be used to define new pages on website. If you need that - you can create a view configured to be a menu, and urls in that menu, would redirect user to the same view he is now, but with different contextual filters.
From the programatically perspective, you can always use hook_url_inbound_alter() and hook_url_outbound_alter() hooks for that.
You can give a try to Query Parameters To URL module or if you're using Search API and Facets, you may use Facet API Pretty Paths.
You can also convert your view to use arguments in your path and use Redirect module.
Apart the above, there is no easy way to achieve that, as there is still pending feature for Drupal 8; see Allow query strings in URL aliases.
When you're using panels which uses views and in example better exposed filters, you can do some few hacks like (URL example: /panel_url?category=123):
/**
* Implements hook_url_inbound_alter().
*/
function foo_url_outbound_alter(&$path, &$options, $original_path) {
if (arg(0) == 'panel_url') {
// Convert URL like: /panel_url?category=29 into /panel_url/term_name (SEO friendly)
$path_info = parse_url($path);
switch (@$path_info['path']) {
case 'panel_url/term_name':
case 'panel_url/term_name2':
$path = 'panel_url/all'; // Convert loopy urls into base url
}
if (strpos($path, '?category=') !== FALSE) { // Convert term id into human name
list(, $tid) = explode('=', current(explode('&', $path_info['query']))); // get tid from URL
$term_name = strtolower(taxonomy_term_load((int)$tid)->name);
$path = '/panel_url' . '/' . $term_name; // See also: $path_info['path']
}
}
}
For more information, please see Passing Argument from URL in Panel to View Pane or Block.
Finally, you can use hook_menu() to define your custom menu callbacks and load your view programmatically.
You could use the following code.
function hook_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == "abcd") {
$form['#submit'] = array('custom_search_redirect');
}
}
function custom_search_redirect($form, &$form_state) {
$form_state['redirect'] = "members/valuea/valueb;
}