-2

我想切换链接的协议。如果是http,应该变成https,https应该变成http。我正在使用 pre_replace 但出了点问题。

有人可以查看我的代码并告诉我在思考过程中缺少什么吗?

这是代码:

           $pattern = array(
                0 => '/^(http\:)/',
                1 => '/^(https\:)/'
            );
            $replace = array(
                0 => 'https:',
                1 => 'http:'
            );

            ksort($pattern);
            ksort($replace);

            $url = 'http://someurl.com';

            echo $url."<br />";

            $url = preg_replace($pattern, $replace, trim($url),1);

            die($url);
4

5 回答 5

3
  1. 你不需要 escape :,它不是特殊字符。
  2. 您不需要捕获组()
  3. 您不需要调用ksort(),您的数组在声明它们时已经按键排序。
  4. 您的代码似乎将“http”替换为“https” 并将“https”替换为“http”。为什么?

$url = preg_replace('/^http:/', 'https', trim($url));如果您只是想强制使用 https,它将正常工作。

编辑

我仍然不知道为什么有人想要同时切换 http/https,但是你去吧:

function protocol_switcheroo($url) {
  if( preg_match('/^http:/', $url) ) {
    return preg_replace('/^http:/', 'https:', $url); // http to https
  } else if( preg_match('/^https:/', $url) ) {
    return preg_replace('/^https:/', 'http:', $url); // https to http
  } else {
    return $url; // for URIs with protocols other than http/https
  }
}

您需要将要替换的调用分开,以免像问题中的原始代码那样意外地将它们链接起来。

于 2013-03-05T16:17:38.930 回答
1

这不适用于 http -> https(但适用于 https -> http)的原因是 preg_replace() 首先使用第一组键/变量 (0) 将 http 更改为 https,然后立即返回https -> http,因为每个数组中的第二组变量 (1) 是另一个有效匹配项。

于 2013-03-05T16:24:37.623 回答
1
//$url = 'http://example.com/https://www';
$url = 'https://example.com/http://www';

$url = (0 === strpos($url, 'http:'))
    ? substr_replace($url, 's:', 4, 1)
    : substr_replace($url, '', 4, 1);

echo $url;

这将转换HTTP -> HTTPSHTTPS -> HTTP

它不使用速度较慢的正则表达式,也不使用str_replace()可能无意中替换 URL 其他部分的正则表达式。它只会替换第一个前缀。

Breakdown :查看 URL 是否以HTTPS开头,http:是否会替换第 5 个字符。否则,它将用任何内容替换第 5 个字符,使其成为 HTTP。:s:s

于 2013-03-05T16:37:06.243 回答
0

您的网址被替换了两次。首先,第一个表达式匹配并http://someurl.com变为https://someurl.com。然后,第二个表达式匹配并https://someurl.com变为http://someurl.com

使用另一个示例更容易看到:

echo preg_replace(
    array('/fox/',  '/turtle/'),
    array('turtle', 'sparrow'),
 'fox', 1);

...打印出来sparrow

于 2013-03-05T16:27:19.790 回答
0

您遇到的问题是preg_replace()两个替换一个接一个,因此在第一个运行后,第二个会反转第一个的效果。

您需要在一个表达式中指定这两种模式才能让它们一起运行。

我建议使用preg_replace_callback()而不是preg_replace(). 有了这个,您可以编写更复杂的输出表达式,从而更容易将它们组合成一个模式。像这样的东西可以解决问题:

$outputString = preg_replace_callback(
    '/^(http|ftp)(s)?(:)/',
    function($matches) {return $matches[1].($matches[2]=='s'?'':'s').':';},
    $inputString
);

希望有帮助。

[编辑]在 OP 发表评论后,编辑了代码,使其适用于ftp/ftpshttp/ 。https

于 2013-03-05T16:43:13.057 回答