I have a page my/topics. The page presents content based on the user's selection from another page. Having made the selection, it and other information is passed to the page via a query string:
mydomain.com/my/topics/?choice=topic1...
I have no control over the creation of the incoming path. For the processing of the path and for SEO I need the path to instead be:
mydomain.com/my/topics/topic1
In both cases the target is my/topics, but the processing I need from that point depends on being able to access the additional information as part of the URL instead of as a query string.
The available topics are a large non-static list. It might be possible to do some regex magic in .htaccess to handle it as a redirect, but I'd rather handle it within Drupal, if possible.
To that end I've used OutboundPathProcessorInterface. The class is listed, below. The problem I am having is that the path is not changed in the browser address bar. If I put my/topics in a menu link on the page, or a link in the body text, it does become my/topics/topic1 in each of the links, and in the address bar on a subsequent click, but not in the address bar of the page that is rendered as part of the altering of the path... it appears as my/topics.
I have commented out the 'if' statement that limits the change to just that path, and the result is the same on admin/structure, for example. The browser shows admin/structure, but the link to it in the admin menu when hovered over shows admin/structure/topic1.
You'll note that I have the priority of the module being -32766 (I've also tried just -1). No difference.
url_remap.services.yml
services:
url_remap.path_processor:
class: Drupal\url_remap\UrlRemapOutboundPathProcessor
tags:
- { name: path_processor_outbound, priority: -32766 }
UrlRemapOutboundPathProcessor.php
namespace Drupal\url_remap;
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Symfony\Component\HttpFoundation\Request;
class UrlRemapOutboundPathProcessor implements OutboundPathProcessorInterface {
function processOutbound($path, &$options = array(), Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {
$append = '';
if ($path == "/my/topics") {
if (sizeof($options['query']) > 0) {
if (array_key_exists('choice', $options['query'])) {
$append = substr($path, strlen($path) - 1, 1) != '/' ? '/' . $options['query']['choice'] : $options['query']['choice'];
}
}
}
return $path . $append;
}
}