2

I have a module where I created a route /page/tag/{term} that uses a controller for modifications to how the term page is handled.

The problem is that when any page displays these term links, they don't use the custom route, but the default /taxonomy/term/{id}.

How can I tell the taxonomy term links to use my custom route?

Adding the path as the term alias skips over the custom route entirely.

OR, how would I get rid of the custom route and create a pathauto pattern using the same path, but tell those pages to use my custom controller?

I have tried both methods without success...


Here is what I've tried with modifying the existing route:

modulename.services.yml

services:
  modulename.route_subscriber:
    class: Drupal\modulename\Routing\RouteSubscriber
    tags:
      - { name: event_subscriber, priority: 100 }

modulename/src/Routing/RouteSubscriber.php

namespace Drupal\modulename\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

/**
 * Listens to the dynamic route events.
 */
class RouteSubscriber extends RouteSubscriberBase {

    /**
    * {@inheritdoc}
    */
    protected function alterRoutes(RouteCollection $collection) {
        if ($route = $collection->get('entity.taxonomy_term.canonical')) {
            // i've tried both of these
            $route->addDefaults(['_controller' => '\Drupal\modulename\Controller\ListController::list_by_tag' ']);
            $route->addDefaults(['_title' => 'test']);
        }
    }

}

Edit: after seeing this, I thought about keeping my custom route and using the alterRoutes to change the links...

$route->setPath('/page/tag');

That worked, but it adds on ?taxonomy_term=123

How can I get the term name into the url? /page/tag/term


Update:

Still can't figure out how to get the term name from the route (without loading the taxonomy entity - I'd imagine that is too much load)

Also, I will need to make sure I'm in a specific vocabulary before changing the route.

Any ideas?

4
  • you do not get rid of the original route, get rid of your route and alter the existing route instead. routes are hardcoded like links were in <=d7 so altering them makes no sense.
    – user21641
    Aug 14, 2017 at 20:07
  • How would I go about doing this and having the existing route use my custom controller?
    – Deez
    Aug 14, 2017 at 20:31
  • Create event subscriber service from \Symfony\Component\EventDispatcher\EventSubscriberInterface and listen to \Drupal\Core\Routing\RoutingEvents::ALTER event.
    – user21641
    Aug 14, 2017 at 20:39
  • ´RouteSubscriberBase` already contains this even listener. See drupal.org/docs/8/api/routing-system/…
    – 4uk4
    Aug 14, 2017 at 21:37

1 Answer 1

1

In my case, I'm also using a RouteSubscriber to change the default controller responsible for handling taxonomy term entities. I also wanted to use a custom template only for a specific taxonomy (called my_taxonomy in the example below).

Here is the code for the RouteSubscriber:

<?php

namespace Drupal\my_module\Routing;

use Drupal\Core\Routing\RoutingEvents;
use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

class RouteSubscriber extends RouteSubscriberBase {

    /**
     * {@inheritdoc}
     */
    protected function alterRoutes(RouteCollection $collection) {
        if ($route = $collection->get('entity.taxonomy_term.canonical')) {
            $route->setDefaults([
                '_controller' => '\Drupal\my_module\Controller\DefaultController::listAll',
            ]);
        }
    }

    /**
     * {@inheritdoc}
     */
    public static function getSubscribedEvents() {
        $events[RoutingEvents::ALTER] = ['onAlterRoutes', -200];
        return $events;
    }

}

And here is the code for the controller. Note that a custom render array can be returned only for terms of the specific taxonomy my_taxonomy. All other terms fall back to the default controller used by the views module in the original route:

<?php

namespace Drupal\my_module\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\taxonomy\Entity\Term;
use Drupal\views\Routing\ViewPageController;
use Symfony\Component\HttpFoundation\Request;

class DefaultController extends ControllerBase {

    public function listAll(Request $request) {
        $render = [];

        $tid = \Drupal::routeMatch()->getRawParameter('taxonomy_term');
        $term = Term::load($tid);
        $bundle = $term->bundle();
        if ($bundle == 'my_taxonomy') {
            // render array for your custom template
        } else {
            // falls back to the default ViewPageController to handle all other taxonomies
            $viewPageController = new ViewPageController();
            $render = $viewPageController->handle('taxonomy_term', 'page_1', \Drupal::routeMatch());
        }

        // Return render array
        return $render;
    }

}
1
  • This is almost functional. In order for term-pages from other vocabularies to work RouteSubscriber needs one small addition: $route->setDefaults([ '_controller' => '\Drupal\my_module\Controller\DefaultController::listAll', 'view_id' => 'taxonomy_term' ]); The view_id default needs to be added so other vocabularies can load the proper view. May 31, 2022 at 11:59

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.