我有超过 1,000 个格式为
https://example.com/archives/<NNNNNN>.php
的单独文件,其中 N
是一个整数。
我需要保持现有的结构不变,尽管我可以添加它。在这种情况下,每个页面都有一个唯一的
data-url-title="<url-friendly-title>"
。
我希望我的
.htaccess
配置来确定读取的文件,使用正则表达式提取 url-friendly-title
,并重写最终 URL 以替换 <NNNNNN>
,格式为 https://example.com/archives/url-friendly-title.php
(然后我会删除 .php
从它开始——但我没有走那么远)。
# Enable rewriting
RewriteEngine On
# Match the old archive URL
RewriteCond %{REQUEST_URI} ^/archives/([0-9]+)\.php$
# Check that the file exists
RewriteCond expr "-f '%{DOCUMENT_ROOT}/archives/%1.php'"
# Extract data-url-title from the file content
RewriteCond expr "file('%{DOCUMENT_ROOT}/archives/%1.php') =~ /data-url-title=\"([^\"]+)\"/"
# Rewrite the URL to the new friendly URL
RewriteRule ^archives/([0-9]+)\.php$ /archives/%1.php [R=301,L]
任何使用此配置的尝试都会导致我的整个网站抛出内部服务器错误并显示日志消息
RewriteCond: bad flag delimiters
。
我认为我的正则表达式中没有任何空格。
我已将我的
.htaccess
文件转换为 Unix 结尾。
我查看了许多已回答的问题,它们似乎表明,在 Apache 2.4.x 中,可以使用
RewriteCond expr "<expression>"
: 从外部文件读取变量
我无法让它工作。还有什么:
htaccess 测试器 对于两个
Unsupported TestString: expr
语句都会抛出 RewriteCond expr
。
.htaccess check 特别声明
RewriteCond: bad flag delimiters
为 第二 RewriteCond 行。
更新:我尝试将
s
推迟到 RewriteCond expr "file('%{DOCUMENT_ROOT}/archives/%1.php') =~ /data-url-title=\"([^\"]+)\"/s"
进行换行匹配,但结果是相同的:浏览器中的内部服务器错误; RewriteCond: bad flag delimiters
在日志中。
嗯,因为根据变量inin重写页面URL,仅使用
.htaccess
,似乎行不通。 。 。这就是我所做的:
首先,我检查所需的模式并将其传递给
redirect.php
处理程序脚本。然而,这里有一个技巧,我还将重写的 URL 传递给处理程序脚本,以确保使用旧式 URL 的任何人仍然可以获得有效的结果。
# Enable rewriting
RewriteEngine On
# Redirect numeric IDs to friendly URLs
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^archives/(\d+)\.php$ /archives/redirect.php?id=$1 [R=301,L,QSA]
# Handle friendly URLs
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^archives/([a-z0-9-]+)/?$ /archives/redirect.php?title=$1 [L,QSA]
这就是乐趣的开始。代码中的注释解释了脚本的工作原理,但现在的重点是:
https://example.com/archives/friendly-name
工作正常https://example.com/archives/000001.php
仍会重定向到 example.com/archives/friendly-name
,以实现向后兼容性<?php
// Iterate through all available `<NNNNNN>.php` files and check
// whether file contains the `data-url-title` attribute
function findMatchingFile($fileFormat, $isId = false) {
$files = glob(__DIR__ . "/*.php");
foreach ($files as $file) {
if (basename($file) === 'redirect.php') continue;
$content = file_get_contents($file);
if ($isId) {
if (basename($file) === $fileFormat . '.php') {
if (preg_match('/data-url-title="([a-z0-9-]+)"/', $content, $matches)) {
return array($file, $matches[1]);
}
}
} else {
if (preg_match('/data-url-title="' . preg_quote($fileFormat, '/') . '"/', $content)) {
return array($file, $fileFormat);
}
}
}
return false;
}
// Get input from query parameters
$input = isset($_GET['id']) ? $_GET['id'] : (isset($_GET['title']) ? $_GET['title'] : '');
// Sanitize input
$input = trim(preg_replace('/[^a-z0-9-]/', '', strtolower($input)), '-');
// Find file matching input: if searchin by ID and matching file is found,
// redirect to archive URL; if searching by title, include matching fild
if (!empty($input)) {
$result = findMatchingFile($input, isset($_GET['id']));
if ($result) {
if (isset($_GET['id'])) {
header("HTTP/1.1 301 Moved Permanently");
header("Location: /archives/" . urlencode($result[1]));
exit();
} else {
include($result[0]);
exit();
}
}
}
header("HTTP/1.0 404 Not Found");
echo "404 Not Found";
?>