我需要一个PHP路由脚本,它使用具有许多重定向的现有htaccess文件,如:

Redirect 302 /some.ts http://targeturl/target.ts

我已经搜索了很多代码示例,但找不到一个合适的,我绝对是一个PHP初学者.它应该是PHP开发人员服务器的路由.

如果有人能在这里给我举个例子就好了.谢谢!

Update

我现在有了第一次脚本try (在一些人工智能的帮助下):

<?php

// Get the requested URI
$requestURI = $_SERVER['REQUEST_URI'];
$filePath = __DIR__ . $requestURI;

/**
 * Retrieves the redirect rules from the .htaccess file
 *
 * @return array
 */
function getHtaccessRedirectRules()
{
    // Get the contents of the .htaccess file
    $htaccessContent = file_get_contents('/www/.htaccess');

    // Extract the redirect rules using a regular expression
    $pattern = '/Redirect 302\s+(?P<expr>[^\s]+)\s+(?P<file>[^\s]+)/';
    preg_match_all($pattern, $htaccessContent, $matches, PREG_SET_ORDER);

    // Build an array of redirect rules
    $redirectRules = [];
    foreach ($matches as $match) {
        $oldPage = str_replace('"', '', $match[1]);
        $newPage = str_replace('"', '', $match[2]);
        $redirectRules[$oldPage] = $newPage;
    }
    
    return $redirectRules;
}

// Check if the requested file exists
if (file_exists($filePath) && !is_dir($filePath)) {
    // Serve the file directly
    return false;
}

// Retrieve the redirect rules from the .htaccess file
$redirectRules = getHtaccessRedirectRules();

// Check if the requested URI matches any redirect rules
foreach ($redirectRules as $oldPage => $newPage) {
    if ($requestURI === $oldPage) {
        // Redirect to the new page
        header("Location: $newPage", true, 302);
        exit;
    }
}

// If no redirect rule matches, serve a 404 page
http_response_code(404);
echo '404 Page Not Found';

?>

它仍然不起作用,但我用以下命令判断了正则表达式: https://www.phpliveregex.com/#tab-preg-match

结果对我来说看起来还不错. 目前,我只收到来自PHP Dev服务器的"接受"和"关闭"消息.

也许其他人看到了一些问题(S).

谢谢!

推荐答案

因此,您已经找到的这个正则表达式模式的匹配组号是错误的:

    foreach ($matches as $match) {
        $oldPage = str_replace('"', '', $match[2]);
        $newPage = str_replace('"', '', $match[3]);
        $redirectRules[$oldPage] = $newPage;
    }

需要分别为12:

$pattern = '/Redirect 302\s+(?P<expr>[^\s]+)\s+(?P<file>[^\s]+)/';
#           |               `-----(1)------´   `------(2)-----´|
#           `-------------------------(0)----------------------´

正则表达式模式的另一个改进是删除了匹配组的命名,因为您不使用它们:

$pattern = '/Redirect 302\s+([^\s]+)\s+([^\s]+)/';
#           |               `-(1)--´   `-(2)--´|
#           `---------------(0)----------------´

这也是一个小的优化,因为PHP将使用更少的内存,$matches数组则具有更少的项,并且可以节省每个匹配项两个字符串键的内存.在内部,这也有一个好处,那就是PHP可以优化这样的数组,因为它们是list(100),这意味着从整数键0开始,后面所有的键都是连续的整数.然后,PHP可以优化(内存和速度).


        $oldPage = str_replace('"', '', $match[1]);
        $newPage = str_replace('"', '', $match[2]);
        $redirectRules[$oldPage] = $newPage;

这是对每个$Match进行的两个str_place()调用,它们执行相同的搜索和替换,只是主题不同.

Str_place()可以对主题数组进行操作.因此,这两个函数调用可以替换为一个:

        [$oldPage,  $newPage ] = str_replace('"', '', [$match[1], $match[2]]);
        $redirectRules[$oldPage] = $newPage;

在PHP中,这通常是一种优化,因为函数调用的开销是relatively%,而数组的创建和析构则不是这样.但这是在某种程度上,您通常需要使用您自己的数据运行指标,然后将不同的实现相互比较.因此,好处不是这里的速度,而是配对更好地对齐,因此更直接的代码更容易维护.


接下来是PHP中的一些真正的优化技巧(假设您没有大量的键冲突):

在请求URI中查找可能的重定向.在原始代码中,我们有一个foreach循环(在php中已经很快了)来比较数组key是否与请求URI匹配:

// Check if the requested URI matches any redirect rules
foreach ($redirectRules as $oldPage => $newPage) {
    if ($requestURI === $oldPage) {
        // Redirect to the new page
        header("Location: $newPage", true, 302);
        exit;
    }
}

因为这基本上是在数组($redirectRules)中查找key,所以PHP通过直接访问/查询数组中的项来更快地完成这一操作.因为如果涉及字符串键,则PHP在内部对数组键使用散列映射--这就是为什么可以优化作为列表的数组,不需要对它们进行昂贵的字符串散列,所有键都是从0开始的连续整数--通过键直接测试数组项以测试其是否存在(通常)比在数组上循环更快.当第一个条目匹配时,循环非常快,但循环不能从PHPS内部数组哈希映射中受益,无论它是第一个还是最后一个,在映射中查找项都要有效得多.

这已经解释得很多了,关键部分是,在PHP中,我们可以使用数组作为映射(字符串键、关联数组),当键可以取代循环时,键的查找就是一种优化.

$newPage = $redirectRules[$requestURI] ?? null

仅当存在请求URI的重定向规则时才设置变量$NewPage.

由于有两种可能的结果--数组有该键or的成员,而不是--我们提供键测试失败的情况的值.这适用于null-coalescing operator("??").PHP中未定义的数组条目会发出警告,除非正在使用??运算符来处理这种情况并提供要使用的值.

这里我们使用null值,这意味着有一个值,但它不是一个值.因此,它很好地表达了我们正在寻找的内容:未找到的条目.

// Check if the requested URI matches any redirect rules
if ($newPage = $redirectRules[$requestURI] ?? null) {
    // Redirect to the new page
    header("Location: $newPage", true, 302);
    exit;
}

这种编写代码的方式在PHP中很常见,我倾向于只在if-子句中停止它,也就是if-子句中有is个变量赋值.这取决于上下文,这是否是预期的,因此赋值可以在If和If Then仅对变量操作之前完成,甚至可以清楚地表明我们正在寻找一个非空的变量:

// Check if the requested URI matches any redirect rules
$newPage = $redirectRules[$requestURI] ?? null;
if (!empty($newPage)) {
    // Redirect to the new page
    header("Location: $newPage", true, 302);
    exit;
}

Further:下面是一个如何在磁盘上存储PHP数组并稍后将其加载回磁盘的示例:Answer to: How do I store an array in a file to access as an array later with PHP?

Php相关问答推荐

为什么注册SIGHUP的处理程序函数会阻止在PHP CLI中等待输入时点击X关闭Xterm窗口?""

未在moodle上运行的计划任务

Symfony Api平台:按自定义实体方式排序结果

使用php创建表格和插入数据

使用php ZipArhive类将Zip压缩文件分成多个部分

如何在execute语句中使用存储过程参数?

使用与OpenSSL命令行兼容的AES-256-CTR为大型文件创建php代码OpenSSL加密

PHP SimpleXML:按属性值访问 node

Font Awesome 加载图标未显示在 WooCommerce 管理员列表中

如果在 APIPlatform 3.1 中的同一资源上使用处理器,Messenger 将无法工作

PHP向API发送curl请求

在shopware 6.5上可以使用什么事件来判断刚刚支付的订单的状态

Composer自动加载器重复了子类的类文件路径

在 Symfony 测试中何时使用 TestCase 而不是 KernelTestCase

如何使用在产品快速编辑菜单前端的自定义框中 Select 的值更新 woocommerce 产品属性值?

如何从此字符串创建 Carbon 对象:2022-06-21T05:52:46.648533678Z?

Laravel 从嵌套数组的第二级获取最后一项

如何使用先前 SELECT 的结果来 SELECT SQL 数据

为什么 PDO 允许使用带命名占位符的索引数组,但仅在禁用仿真时才允许?

Laravel 自定义中间件:ERR_TOO_MANY_REDIRECTS