14

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
4
  • Excellent question. AFAIK, it's not possible as of now, except with code. Found this which seems to solve the problem, but didn't test it yet.
    – Countzero
    Feb 20, 2012 at 8:03
  • You are having problems with clean URL, read this post drupal.org/getting-started/clean-urls Jan 17, 2013 at 10:20
  • 1
    I have clean url enabled, for other pages it is in seo friendly notation, but for exposed filter only it's query string eg when I go to any article, url is seo friendly. Please let me know if I am missing something. Jan 17, 2013 at 10:25
  • I can see there may be some point to this, but before going to the trouble I'd actually look for evidence. What matters more: an "SEO-friendly URL" or content that corresponds to common searches? If a results page has a strong title I suspect that'll be much more valuable than its URL. I'd certainly concentrate on content first, in any case. Oct 22, 2013 at 9:24

5 Answers 5

9

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.

2
  • thanks. It doesn't look trivial. I mainly want it for SEO purposes because search engine spiders don't crawl past a form. I might just use a second view with contextual filters and embed my exposed filter block. Then I just need some javascript to have the exposed filter submit to my original view.
    – uwe
    Feb 20, 2012 at 16:54
  • hmm, if I do that I could use javascript to modify the form GET url from page?name1=value1&name2=value2 to page/value1/value2 stackoverflow.com/questions/5815995/…. If javascript is disabled I have my original view as a fallback.
    – uwe
    Feb 20, 2012 at 17:00
4

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

into http://example-site.com/events/p/field_category_id/0__100--1__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.

1
  • 1
    What about Drupal 8? Jan 11, 2020 at 16:30
1

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:

  1. 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).

  2. 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.

1

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.

-1

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;
}
1
  • Views is not aware of the new url with your solution!! Jul 17, 2014 at 18:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.