I wanted to create an automatic alias for nodes that have a date set. The pattern should be /events/node-title. Because the content type is also used for regular pages, I had to do this programmatically. Here is how I did it:
/**
* Implements hook_node_insert().
*/
function MYMODULE_node_insert(NodeInterface $node) {
if ($node->getType() == 'page') {
MYMODULE_create_alias($node);
}
}
/**
* Implements hook_node_update().
*/
function MYMODULE_node_update(NodeInterface $node) {
if ($node->getType() == 'page') {
MYMODULE_create_alias($node);
}
}
/**
* Helper function to create alias.
*/
function MYMODULE_create_alias(NodeInterface $node) {
if (isset($node->field_date) && !empty($node->field_date->value)) {
// Check if Pathauto is enabled and set the pathauto state.
if (\Drupal::moduleHandler()->moduleExists('pathauto')) {
$node->path->pathauto = \Drupal\pathauto\PathautoState::SKIP;
}
// Base alias
$base_alias = '/events/' . \Drupal::service('pathauto.alias_cleaner')->cleanString($node->label());
$alias = $base_alias;
// Initialize a counter
$counter = 0;
// Check if the alias already exists and modify it if necessary
while (true) {
$existing_alias = \Drupal::entityTypeManager()->getStorage('path_alias')
->loadByProperties([
'alias' => $alias,
'langcode' => $node->language()->getId(),
]);
if (!empty($existing_alias)) {
// Alias exists, modify it and check again
$counter++;
$alias = $base_alias . '-' . $counter;
} else {
// Alias is unique, break the loop
break;
}
}
// Create and save the unique alias
$path_alias = \Drupal::entityTypeManager()->getStorage('path_alias')->create([
'path' => '/node/' . $node->id(),
'alias' => $alias,
'langcode' => $node->language()->getId(),
]);
$path_alias->save();
}
}
This snippet takes into account already existing alias, language etc. Cheers!