Managing redirects in Drupal can be a real headache, especially when you’ve got a bunch of URLs to handle. Whether you’re updating content, rebranding, or just cleaning house, getting those redirects right is crucial for keeping your SEO strong and your users happy. Here’s a quick way to automate redirect management in Drupal 10 with some custom PHP that hooks into the Redirect module.
Why Automate Redirects?
Redirects are the unsung heroes that keep your users and search engines on the right track. But manually setting them up? That’s a time suck and a recipe for mistakes, especially if your site’s big. Automating this process saves you time, cuts down on errors, and makes sure your redirects are always spot-on.
The Code: Automating Redirect Creation
Here’s the code that gets the job done. This PHP function automates redirect creation by checking if a redirect already exists, verifying the target path, and logging any issues. It’s the set-it-and-forget-it solution you need to keep your site running smoothly.
<?php
use Drupal\redirect\Entity\Redirect;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Logger\LoggerChannelTrait;
use Drupal\Core\Path\AliasManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
/**
* Creates redirects based on predefined source and target paths.
*/
function create_redirects() {
$entity_type_manager = \Drupal::entityTypeManager();
$alias_manager = \Drupal::service('path_alias.manager');
$redirects = [
["/updates", "/nieuws"],
["/about", "https://example.com/about"], // external redirect
// add new redirects here
];
foreach ($redirects as $redirect) {
$source = $redirect[0];
$target = $redirect[1];
if ($source === $target) {
// Skip if the source and target are the same.
\Drupal::logger("redirect_import")->notice("Source and target are the same for @source. Skipping.", [
"@source" => $source,
]);
continue;
}
// Load existing redirects by source path.
$existing_redirects = $entity_type_manager->getStorage("redirect")->loadByProperties([
"redirect_source__path" => $source,
]);
$redirect_exists = false;
// Check if any existing redirects match the target URI.
foreach ($existing_redirects as $existing_redirect) {
if ($existing_redirect->get('redirect_redirect')->uri === (strpos($target, 'http') === 0 ? $target : "internal:" . $target)) {
$redirect_exists = true;
break;
}
}
if ($redirect_exists) {
// Skip if the redirect already exists.
\Drupal::logger("redirect_import")->notice("Redirect from @source to @target already exists. Skipping.", [
"@source" => $source,
"@target" => $target,
]);
continue;
}
// Check if the target is an internal path and exists.
if (strpos($target, 'http') !== 0) {
$path = $alias_manager->getPathByAlias($target);
if ($path === "/" . $target) {
// Target does not exist, log a message.
\Drupal::logger("redirect_import")->notice("Target path @target does not exist. Skipping redirect for @source.", [
"@target" => $target,
"@source" => $source,
]);
continue;
}
}
// Create the redirect.
try {
$redirect_entity = Redirect::create([
"redirect_source" => [
"path" => $source,
"query" => [],
],
"redirect_redirect" => [
"uri" => (strpos($target, 'http') === 0 ? $target : "internal:" . $target),
],
"language" => "nl",
"status_code" => 301,
]);
$redirect_entity->save();
} catch (EntityStorageException $e) {
// Log the error but do not throw it to avoid breaking the script.
if (strpos($e->getMessage(), 'Duplicate entry') !== false) {
\Drupal::logger("redirect_import")->notice("Duplicate redirect entry for @source to @target. Skipping.", [
"@source" => $source,
"@target" => $target,
]);
} else {
\Drupal::logger("redirect_import")->error("Failed to create redirect for @source to @target: @message", [
"@source" => $source,
"@target" => $target,
"@message" => $e->getMessage(),
]);
}
} catch (\Exception $e) {
// Catch any other exceptions and log them.
\Drupal::logger("redirect_import")->error("An unexpected error occurred while creating redirect for @source to @target: @message", [
"@source" => $source,
"@target" => $target,
"@message" => $e->getMessage(),
]);
}
}
}
Running the Script with Drush
Once you've defined your redirects and implemented the `create_redirects` function, you can easily execute it using Drush. This command-line tool is indispensable for Drupal developers, providing a simple way to run PHP code directly within your site's environment. To run the `create_redirects` function, use the following Drush command:
drush php-eval "create_redirects()"
This command executes the function within your Drupal environment, creating the necessary redirects, logging any issues, and skipping duplicates to prevent errors.
Key Considerations
- **Duplicate Handling:** The script checks for existing redirects before attempting to create a new one. This prevents database integrity errors and ensures that you don't create duplicate redirects.
- **Target Path Validation:** Before creating a redirect, the script validates that the target path exists. If it doesn't, the redirect is skipped, and a message is logged.
- **Error Logging:** Any issues encountered during the process are logged using Drupal's logging system, making it easy to troubleshoot and ensure that all redirects are created as expected. By automating your redirect management in Drupal 10, you can maintain a clean, efficient site structure while avoiding common pitfalls associated with manual redirect handling. This approach not only saves time but also ensures that your site's SEO remains intact during content migrations, rebrands, or other major changes.