使用 PHP 重定向几千个 URL
Redirecting a few thousand URLs using PHP
我正在迁移一个需要大约 5000 次重定向的站点,格式如
http://www.acme.org/content/item.aspx?id=123
重定向到
http://www.acme.org/resources/articles/why-acme-is-great
通常我会通过 .htaccess 或 nginx 模块完成此操作。但是我在 WordPress 特定主机 Pantheon 上,它不允许访问它。
所以我能想到的唯一解决办法就是使用PHP。以下是工作。那里有一些特定于 WordPress 的代码可以防止 WordPress 抛出 404。
add_filter('template_redirect', 'my_404_override');
function my_404_override()
{
global $wp_query;
if (strpos($_SERVER['REQUEST_URI'], 'issues') !== false) {
$redirectURL = "/resources";
if (strpos($_SERVER['REQUEST_URI'], '123') !== false) {
$redirectURL .= "/articles/why-acme-is-great/";
}
}
if (!empty($redirectURL)) {
status_header(200);
$wp_query->is_404 = false;
header('HTTP/1.0 301 Moved Permanently');
header('Location: http://www.acme.org' . $redirectURL);
}
}
这很好用。但是我有两个问题:
- 有5000个列表,这对性能会有什么样的影响?我打算使用一些更大的条件,然后缩小范围(在上面的示例中,我首先检查
/resources
,然后再查看特定 ID。
- 虽然理论上永远不需要修改此列表,但就语法和逻辑而言,它感觉像是一个丑陋的解决方案。有没有我没有想到的更好的方法?
您的问题是您需要将旧内容映射到新内容。将自定义字段添加到每个 post 内容以达到 "old_url=123" 的效果,然后为 post-slug 执行 wp_query。我假设您的旧 ID(即 123)不一定与新 ID 匹配。为每个可能的 URL 添加条件的方法不可行且难以维护。
当您为每个包含 "old content" 的新 post / 页面添加一个字段时,您的代码可以是这样的:
add_filter('template_redirect', 'my_404_override');
function my_404_override()
{
global $wp_query;
$old_url = $_SERVER['REQUEST_URI'];
$results = $wpdb->get_results(
$wpdb->prepare( "SELECT wp_posts.guid, redirect_url FROM wp_posts LEFT JOIN wp_post_meta ON wp_posts.ID = wp_post_meta.post_id WHERE wp_post_meta.old_url = %s LIMIT 1", $old_url ));
$redirectURL = $results[0]['guid'];
}
if (!empty($redirectURL)) {
status_header(200);
$wp_query->is_404 = false;
header('HTTP/1.0 301 Moved Permanently');
header('Location: ' . $redirectURL);
}
}
这是伪代码;但一般的想法是无论如何都要查询一行;并且对性能的影响可以忽略不计,因为只有在 404 的情况下,您检查是否存在重定向并且该查询 returns 只有一行。
这种方法存在问题,例如,如果某人在两个 post 上输入相同的数字,则无法确定哪个是最重要的重定向的优先级。您也可以考虑使用插件来解决这个问题。
我正在迁移一个需要大约 5000 次重定向的站点,格式如
http://www.acme.org/content/item.aspx?id=123
重定向到
http://www.acme.org/resources/articles/why-acme-is-great
通常我会通过 .htaccess 或 nginx 模块完成此操作。但是我在 WordPress 特定主机 Pantheon 上,它不允许访问它。
所以我能想到的唯一解决办法就是使用PHP。以下是工作。那里有一些特定于 WordPress 的代码可以防止 WordPress 抛出 404。
add_filter('template_redirect', 'my_404_override');
function my_404_override()
{
global $wp_query;
if (strpos($_SERVER['REQUEST_URI'], 'issues') !== false) {
$redirectURL = "/resources";
if (strpos($_SERVER['REQUEST_URI'], '123') !== false) {
$redirectURL .= "/articles/why-acme-is-great/";
}
}
if (!empty($redirectURL)) {
status_header(200);
$wp_query->is_404 = false;
header('HTTP/1.0 301 Moved Permanently');
header('Location: http://www.acme.org' . $redirectURL);
}
}
这很好用。但是我有两个问题:
- 有5000个列表,这对性能会有什么样的影响?我打算使用一些更大的条件,然后缩小范围(在上面的示例中,我首先检查
/resources
,然后再查看特定 ID。 - 虽然理论上永远不需要修改此列表,但就语法和逻辑而言,它感觉像是一个丑陋的解决方案。有没有我没有想到的更好的方法?
您的问题是您需要将旧内容映射到新内容。将自定义字段添加到每个 post 内容以达到 "old_url=123" 的效果,然后为 post-slug 执行 wp_query。我假设您的旧 ID(即 123)不一定与新 ID 匹配。为每个可能的 URL 添加条件的方法不可行且难以维护。
当您为每个包含 "old content" 的新 post / 页面添加一个字段时,您的代码可以是这样的:
add_filter('template_redirect', 'my_404_override');
function my_404_override()
{
global $wp_query;
$old_url = $_SERVER['REQUEST_URI'];
$results = $wpdb->get_results(
$wpdb->prepare( "SELECT wp_posts.guid, redirect_url FROM wp_posts LEFT JOIN wp_post_meta ON wp_posts.ID = wp_post_meta.post_id WHERE wp_post_meta.old_url = %s LIMIT 1", $old_url ));
$redirectURL = $results[0]['guid'];
}
if (!empty($redirectURL)) {
status_header(200);
$wp_query->is_404 = false;
header('HTTP/1.0 301 Moved Permanently');
header('Location: ' . $redirectURL);
}
}
这是伪代码;但一般的想法是无论如何都要查询一行;并且对性能的影响可以忽略不计,因为只有在 404 的情况下,您检查是否存在重定向并且该查询 returns 只有一行。
这种方法存在问题,例如,如果某人在两个 post 上输入相同的数字,则无法确定哪个是最重要的重定向的优先级。您也可以考虑使用插件来解决这个问题。