The Path(auto) Less Traveled
Building URL Aliases Based on Specific Conditions
Have you ever needed to generate URL aliases for an entity based on specific set of conditions? I was recently on a Drupal 8 project that needed the ability to generate custom URL aliases based on very specific criteria outlined by the client. Out of the box, Pathauto module was not flexible enough to handle the customization, but leveraging its API and providing my own hook implementation in a custom module allowed me to perform conditional checks on data and build the conditional URL structures.
In this blog post, I will walk you through getting set up with some starter code that can be used to provide your own complex logic to generate custom path aliases based on specific business logic.
Specs and logic
Desired URL structure:
Here is an example of the desired URL structure for Article nodes provided by the client:
For “Article” content type:
<tag> = <field_tags_reference> | <field_category_reference>
<slug> = <field_custom_path> | <title>
<url> = article/<tag>/<slug>
Note - The values in angle brackets signify a Drupal field on the node. The pipe ( | ) character is seen as an OR operator, for example for <tag>, only if <field_tags_reference> is not present will it consider using <field_category_reference>.
The first step in deciding the programmatic logic for building proper URL aliases is writing out some pseudo code.
To complete the <url>, we need to determine <tag> and <slug>.
Now we have <tag> and <slug> and have the final URL structure we need in <url> = article/<tag>/<slug>.
We will implement this logic into Drupal programmatically in the next steps.
To get started, you’ll need Pathauto module installed on your Drupal site.
For Drupal 8, you can use `composer require drupal/pathauto`.
Note that Ctools and Token will also be installed, as they are dependencies.
Once Pathauto module is installed, we can edit the Pathauto patterns on an entity type-specific basis.
Configuration → Search and Metadata → URL aliases -> Patterns
- Click the “+Add Pathauto pattern” button.
- For this example, we are generating URL aliases for nodes, so choose “Content” as the Pattern type.
- For the Path pattern, enter “article/[node:title]”.
- For the Content type, choose “Article”.
- Enter a Label of “Article”
If we were to create a new Article node at this point, it would build a nice URL, but Pathauto module out-of-the-box does not allow for condition building of the URLs like we need.
Example: Create a new Article node with the title of “Test”. When the node gets saved, we get a URL of ‘article/test’.
Remember that [node:title] token we added into the pattern above? We added that basically as a placeholder pattern, that we can override in a custom implementation of hook_pathauto_pattern_alter().
I won’t get into creating a custom module, but in your own custom module, implement hook_pathauto_pattern_alter().
The hook implementation looks like:
Your IDE may automatically add the required use statement in the .module file, but if it doesn’t, you can add:
From the alter function, we can figure out what type of data it’s trying to build the URL for, by looking at the $context parameter, which has a key for `module`. The module key of that array provides the entity type, such as node or taxonomy. For this example, we’re only dealing with nodes, but the same technique can be applied to taxonomies or any other entities that allow for pathauto patterns.
We also check the `op` key of the `$context` array to make sure the pathauto pattern generates when nodes are created and/or updated.
Here we can get the node:
Initialize an empty $replacements array, which will have tokens dynamically added to it based on the node-type specific criteria and used to replace the placeholder [node:title] at the end of the logic.
Now that we have the node object, we can easily access the bundle or node type and use it in a switch statement for per-node-type logic rules.
Looking at the data we’re needing to extract from the node to build the URL from, we’re going to need to use a few parts of Drupal API. For entity reference fields, such as tag or category, we can get the referenced entities via:
At the end of the hook_pathauto_pattern_alter() function’s code, there is code to set the new pattern to use which replaces [node:title] with the slash-separated $replacements array.
Now, if we edit our Test article node, enter a value into the field_custom_path field, such as ‘custom-path’ and save, our URL now looks like ‘article/custom-path’.
If we were to add Tags or Categories to the node, the logic will decide which to use in the URL.
For example, if we added a Tag, such as “Test Tag”, and added it to the node via the field_tags_reference term reference field, we end up with a URL such as ‘article/test-tag/custom-path’.
In summary, below is the full function used in this specific example. I hope this blog post helps you realize the flexibility this provides and understand a way to build conditional paths with Pathauto.