1

I'm trying to make my URLs a bit more readable (and persistent) which includes query parameters of a view's page. Usually the URL would look like this when I define an exposed filter which is addressed by the parameter vocabulary-foo: https://www.example.com/view?vocabulary-foo[]=1234. As you might have noticed, this is a filter for taxonomy terms of a specific vocabulary. There are two problems with the usage of IDs in the URL, which I'd like to solve:

  • If I uninstall my custom module that creates the taxonomy terms, these are gone and will get another ID when I install the module again. So I can't assume a link to a specific filtered view page would then still be the same.

  • It's not readable (and memorizable). Using the term's value instead of the ID would probably already help me. On the other hand, if it is possible to define a query parameter preset=something which translates to vocabulary-foo[]=<The id of the term which has a specific value>, I'd rather do that as it enables me to combine multiple query parameters to one preset, which makes it shorter.

In my specific case, the view exposes a form which can be used to search for content. A preset as described would pre-select some form controls with only one clean URL parameter.

One idea that came to my mind was somehow using PHP's $_GET variable and conditionally changing its content before the view is created. Unfortunately, I don't know which hook would be suitable for that.

Has somebody faced a similar issue in the past? How could I solve these problems in Drupal 9? Thanks!

3

There's no easy way to do that .. views better_exposed_filters is quite nice, but does not provide clean urls. Drupal 7 had query_parameters_to_url, for Drupal 8 they link to a sandbox! project ... This may be a starting point for you.

There may be a simpler approach here: Redirect based on query string using a redirect event subscriber:

<?php
    static function getSubscribedEvents()
    {
        $events[KernelEvents::REQUEST][] = array('Redirect', 20);
        return $events;
    }

So you could provide at least clean urls to "somewhere".

1
  • Great answer! I'd just like to add that "smart" redirects can be set on the server side (.htaccess). That way you could design your links to how you like but it requires some technical knowledge and testing. You can use Term names instead of term IDs in Views, often you need to add a Relationship for the Field to get to the name field, then you see the name in the URL. The name alone doesn't solve the ?sth=value infrastructure but it does make it more user friendly. – prkos Dec 17 '20 at 3:02
0

Assuming you have a term name called "Hello World"

So you want https://www.example.com/view?vocabulary-foo=hello-world to work.

/**
 * Implements hook_views_pre_view.
 */
function mymodule_views_pre_view(\Drupal\views\ViewExecutable $view, $display_id, array &$args) {
  $term_name = \Drupal::request()->query->get('vocabulary-foo'); // equals hello-world
  if (!empty($term_name)) {
    $args = [];
    $term_name = str_replace('-', ' ', $term_name); // equals hello world
    // get term id from name
    $term = \Drupal::entityTypeManager()->getStorage('taxonomy_term')
      ->loadByProperties(['name' => $term_name, 'vid' => 'vocabulary_foo']);
    $term = reset($term);
    $term_id = $term->id();
    // set argument
    $args[] = $term_id;
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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