Перенаправление устаревшего URL-адреса
Я перенес сайт, не использующий Drupal, на Drupal. Теперь мне нужно убедиться, что некоторые устаревшие URL-адреса перенаправляются на правильный URL-адрес узла.
Узел имеет идентификатор узла (nid), устаревший идентификатор (field_leg_id), идентификатор элемента (item_id), заголовок (headline_of_the_item) и текст.
Устаревший URL-адрес example.com/type1/201203080034 следует перенаправить на новый URL-адрес example.com/type1/2012/03/08/headline_of_the_item/item_id .
201203080034 - это устаревший идентификатор соответствует 20120308 в новом URL-адресе.
Как перенаправить пользователей на новый узел, если у меня есть только устаревший идентификатор?
обновление
// Redirect based on legacy ID.
$query = db_query("select lid.entity_id, lid.field_legacy_id_value, sid.field_site_content_id_value
from field_data_field_legacy_id lid
inner join field_revision_field_site_content_id sid on lid.entity_id = sid.entity_id
where lid.field_legacy_id_value = $content_id
LIMIT 1");
while ($row = db_fetch_object($query)) {
$s_id = $row->sid.field_site_content_id_value;
$item = node_load($s_id);
if ($item) {
drupal_goto("node/{$item->nid}", array(), 301);
}
}
}
Это дает мне 500 ошибок. Пытался отладить его, но безуспешно.
Обновление на основе @greendemiurge Ниже - это то, что сработало для меня.
function my_item_redirect_item() {
$args = arg();
$content_id = end($args);
$item = my_item_by_legacy_id($content_id);
if ($item) {
drupal_goto("node/{$item->nid}", array(), 301);
}
}
function my_item_by_legacy_id($id) {
// First, check if we have an imported item with this $id (field_legacy_id).
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
->fieldCondition('field_legacy_id', 'value', $id, '=')
->range(0, 1)
->addMetaData('account', user_load(1));
$result = $query->execute();
if (isset($result['node'])) {
$nids = array_keys($result['node']);
return node_load($nids[0]);
}
// Check if there is a node with Nid = $id
return node_load($id);
}
2 answers
Первый вопрос по этому поводу: сколько URL-адресов вам нужно перенаправить? Если это небольшое число, вам может быть лучше использовать .htaccess. Я сомневаюсь, что это так, учитывая ваши модели поведения.
Следующий вопрос заключается в том, достаточно ли информации в старом шаблоне для разрешения текущего узла, или вам нужно создать сопоставления самостоятельно?
Если информации достаточно, возможно, можно использовать перенаправление соответствия - https://www.drupal.org/project/match_redirect . Если это не так именно то, что вам нужно, вы можете реализовать в этом модуле некоторый пользовательский код, основанный на match_redirect_init().
Редактировать
Вышеприведенных дополнений мне достаточно, чтобы сделать пару предложений:
Во-первых, запрос было бы лучше выполнить в виде запроса db_select или поля сущности по стандартным причинам. Более важно, что гораздо эффективнее, если это возможно, позволить SQL выполнять сопоставление, а не цикл while.
Во-вторых, крючок, который, кажется, лучше всего подходит для меня, это hook_menu_get_item_alter(). Другие, у кого больше опыта в маршрутизации меню, возможно, захотят дать некоторые отзывы об этом подходе, но для меня он работает в изолированной среде.
Итак, предполагая, что модуль называется "пользовательский", это то, что, кажется, работает для меня:
function custom_menu_get_item_alter(&$router_item, $path, $original_map) {
$query = new EntityFieldQuery();
// $path is everything after your base URL. I am assuming that this is what
// you have in field_legacy_id.
$query
->entityCondition('entity_type', 'node', '=')
->propertyCondition('status', 1, '=')
->fieldCondition('field_legacy_id', $path);
$results = $query->execute();
$results = array_keys($results['node']);
$result = reset($results);
if (!empty($result)) {
$node = node_load($result);
// This will retain your aliased path if you are using one. Important for
// SEO, especially if you are using a 301.
$path = drupal_get_path_alias("node/{$node}");
drupal_goto($path, array(), 301);
}
}
Я не смог протестировать это заранее, используя описанную вами настройку, поэтому, возможно, потребуется некоторая настройка. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.
Это работает для меня. Мне нужно проверить current_path
, чтобы убедиться, что это параметр необработанного URL, и menu_get_item
, чтобы убедиться, что мы смотрим на случайный URL, а не на /node/10
vs 1234-legacy-url
.
function legacyredirect_menu_get_item_alter(&$router_item, $path, $original_map) {
$query = new EntityFieldQuery();
$path = current_path();
$query
->entityCondition('entity_type', 'node', '=')
->propertyCondition('status', 1, '=')
->addTag('nicedpq')
->fieldCondition('field_legacy_content_id', 'value', $path);
$results = $query->execute();
if (isset($results['node']) && !menu_get_item($path)) {
$results = array_keys($results['node']);
$result = reset($results);
if (!empty($result)) {
$node = node_load($result);
// This will retain your aliased path if you are using one. Important for
// SEO, especially if you are using a 301.
$path2 = drupal_get_path_alias("node/" . $node->nid);
header("Location: $path2", 301);
exit;
}
}
}