I implemented a pre-save hook in a module, which populates nodes by fetching information from various APIs. I can't get my mind around how to add a path alias to newly created nodes.

Is there a function or a class I could use, or should I directly insert data into the database table used for the path alias values?


8 Answers 8


As of Drupal 8.8, path aliases are now entities, and the method of creating a new alias has changed.

To programmatically save an alias, you can do the following:

$path_alias = \Drupal\path_alias\Entity\PathAlias::create([
  'path' => '/unaliased/path',
  'alias' => '/aliased/path',


To create the alias, I first check if the alias was set in the user interface, and if it is empty then I set it manually using the label().

use Drupal\Core\Entity\EntityInterface;

 * hook_entity_insert
function mymodule_entity_insert(EntityInterface $entity) {
    // Convert to lowercase, trim spaces, replace spaces with underscore and then truncate to 60 chars.
    $pathTitle = substr(str_replace(" ","_",trim(strtolower($entity->label()))),0,60);
    if ($entity->toArray()['path'][0]['alias'] == "") {
        $path = \Drupal::service('path.alias_storage')->save("/node/" . $entity->id(), "/mynewpath/" . $pathTitle, "en");

https://www.drupal.org/node/1853148 for more information


To get a clean string, you can use this function from the Pathauto module.

$clean_string = \Drupal::service('pathauto.alias_cleaner')->cleanString('Your very dirty string, with many URL un-friendly parts!');

Source: Drupal: clean a string for use in URLs


Using drupal 8, this is how I did (after a quick search in the pathauto.module file) :

Step 1 : Create the node

$node = Node::create([
    'type' => 'article',
    'title' => 'Test article',
    'langcode' => 'en', // Get it however you want or hardcode it.
    'uid' => [USER_ID] // Get it however you want.

Step 2 : Save the node


Step 3 : Insert the path (make sure the pathauto module is installed and add a pattern for the give node type)


If you need to update the node programmatically, don't forget to update its path : pathauto_entity_update($node) and don't forget to delete it if you delete the node (delete it BEFORE you delete the node of course since the reference will be lost if you don't do that) : pathauto_entity_delete($node)


We're maintaining an inofficial port of the pathauto module. You also need token.module, which you can get from here. Use at your own risk, the configuration structure might change, or core updates might break the module temporarily.

Work just started to get those two modules back to drupal.org.


Also if just going a custom content entity and want to add the url path alias to the form ...

just do

 * Implements hook_entity_base_field_info().
function YOURMODULE_entity_base_field_info(EntityTypeInterface $entity_type) {
 if (in_array($entity_type->id(), ['ENTITYID'], TRUE)) {
$fields['path'] = BaseFieldDefinition::create('path')
  ->setLabel(t('URL alias'))
  ->setDisplayOptions('form', [
    'type' => 'path',
    'weight' => 30,
  ->setDisplayConfigurable('form', TRUE)

  return $fields;



You can just set the value of the path field:

$node->set('path', 'some-alias');
  • I had to also: $node->path->pathauto = PathautoState::SKIP;
    – simesy
    Commented Jan 30 at 2:02

For me and Drupal 9.2+ it was:

use Drupal\node\Entity\Node;
use Drupal\path_alias\Entity\PathAlias;

$node = Node::create(['type' => 'article']);
$node->set('title', 'article en');
    'path' => "/node/" . $node->id(),
    'alias' => '/article_en_alias',
    'langcode' => 'en',
$node_es = $node->addTranslation('es');
$node_es->set('title', 'article es');
    'path' => "/node/" . $node_es->id(),
    'alias' => '/article_es_alias',
    'langcode' => 'es',

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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