当URL缺少http前缀时,请添加http前缀

41

您好,我有一个非常简单的代码

<a href="'.$aProfileInfo['Website'].'" target="_self">
    <div class="callButton">Website</div>
</a>

问题在于,如果用户没有输入 http://,那么链接将指向我的网站而不是外部网站。

我该如何在 PHP 中检查用户是否未输入 http:// 并在缺少时自动添加它?


2
另外,请确保在将用户输入插入到HTML之前进行转义。请参阅htmlspecialchars() - Wilbur Vandrsmith
你可以简化David的答案,使其只占用一行(这样你就可以将其嵌入到HTML中)。请参见:https://dev59.com/kG025IYBdhLWcg3wEhdb#24482058 - Nate
@Nate,实际上,你可以将它简化得更简单。而且正则表达式的方式也可以是一行代码。请参见:https://dev59.com/kG025IYBdhLWcg3wEhdb#31549463 - Evan Kennedy
这可能是 https://dev59.com/nnE85IYBdhLWcg3wejVO 的重复。 - Adam
10个回答

55

我认为你最好使用内置函数parse_url(),它会返回一个带有URL各个组成部分的关联数组

像这样做可以满足你的需求:

 if  ( $ret = parse_url($url) ) {

      if ( !isset($ret["scheme"]) )
       {
       $url = "http://{$url}";
       }
}

4
这是正确的方法! - sk8terboi87 ツ
正则表达式的答案很酷,但我同意这是正确的做法。 - Nate
如果用户输入类似于 foo:bar@foobar/p?arg=val#a 的内容,则会失败。此时,“foo”将被解释为方案。 - Marcky
你可以简单地将 http 替换为 //,以使用当前页面的协议(http / https)。 - Jose Philip Raja
我猜这将强制使用与网站来源相同的协议,因此如果您的网站在https://下,所有链接都将变为https://,并且它们可能没有一个https:// URL。 - al404IT
我放弃了我的正则表达式答案。这是更好的答案。如果方案存在,它将维护该方案;否则,它将假定并在URL前缀中加上“http://”。+1 - Robert Groves

33

我个人使用这个,它部分地来自于php文档

$scheme = parse_url($link, PHP_URL_SCHEME);
if (empty($scheme))
    $link = 'https://' . ltrim($link, '/');

这肯定是第一个答案。完美! - slothstronaut
随着HTTPS成为新的标准,应该将其更新为https。 - Mav2287

20

一个简单的解决方案,可能不适用于所有情况(即包含“https://”的情况):

if (strpos($aProfileInfo['Website'],'http://') === false){
    $aProfileInfo['Website'] = 'http://'.$aProfileInfo['Website'];
}

1
strpos 不是要求先提供 haystack,再提供 needle 吗? - Kevin Ji

10
有两种解决这个问题的方法:URL解析和正则表达式。
有些人会认为URL解析是正确的方法,但是在这种情况下,正则表达式同样适用。我喜欢能够使用简单的一行代码来处理这种情况,特别是当你需要在回显语句中使用一个一行代码来保持可读性时,这将是一个常见的情况。
正则表达式
我们可以使用preg_replace一次性完成这项任务。
preg_replace('/^(?!https?:\/\/)/', 'http://', $aProfileInfo['Website'])

这里使用了“负向先行断言”(negative lookahead)在字符串开头查找“http://”或“https://”。如果找到了其中任意一个,则不会进行替换。如果没有找到,则将字符串的开头(0个字符)替换为“http://”,从而将其作为前缀添加到字符串中而不修改它。
<a href="'. preg_replace('/^(?!https?:\/\/)/', 'http://', $aProfileInfo['Website']).'" target="_self">
    <div class="callButton">Website</div>
</a>

URL Parsing

(parse_url($aProfileInfo['Website'], PHP_URL_SCHEME) ? '' : 'http://') . $aProfileInfo['Website']

这段代码的作用是通过parse_url($aProfileInfo['Website'], PHP_URL_SCHEME)判断链接中是否存在方案。然后使用三元运算符,如果找到方案,则输出'',否则输出'http://'。然后将链接附加在其后面。
上下文如下:
<a href="'.((parse_url($aProfileInfo['Website'], PHP_URL_SCHEME) ? '' : 'http://') . $aProfileInfo['Website']).'" target="_self">
    <div class="callButton">Website</div>
</a>

2
你的正则表达式很聪明,它保留了 https://,但是对于相对 URL(如 //www.example.com)无法正常工作。它还会在 ftp:// 或其他协议前添加 http://。请尝试使用以下代码替代:preg_replace('/^\/\/|^(?!https?:)(?!ftps?:)/', 'http://', $src)(注意:如果不需要 ftp,则可以删除 ftp 的检查)。 - dhaupin

3

您可以使用strpos函数:

// Trim trailing whitespace
$aProfileInfo['Website'] = trim($aProfileInfo['Website']);

// Test if the string begins with "http://"
if (strpos($aProfileInfo['Website'], 'http://') !== 0) {
  $aProfileInfo['Website'] = 'http://' . $aProfileInfo['Website'];
}

1
您还需要考虑到“http(s)”必须位于URL的开头:
if (preg_match('/^https?:\/\//', $aProfileInfo['Website']) === 0) {
    $aProfileInfo['Website'] = 'http://'.$aProfileInfo['Website'];
}

1

如果在字符串中没有找到数组中的任何内容,您可以使用此函数作为通用函数将某些内容附加到字符串末尾。

function httpify($link, $append = 'http://', $allowed = array('http://', 'https://')){

  $found = false;
  foreach($allowed as $protocol)
    if(strpos($link, $protocol) !== 0)
      $found = true;

  if($found)
    return $link;
  return $append.$link;
}

0

像这样的吗?

if (!strpos($aProfileInfo['Website'], 'http://')) {
    $aProfileInfo['Website'] = 'http://' . $aProfileInfo['Website'];
}

0

我相信David的答案是正确的方法,但也可以简化为:

parse_url($aProfileInfo['Website'], PHP_URL_SCHEME)==''?'http://'.$aProfileInfo['Website']:$aProfileInfo['Website']

0

这里是另一个与字符串减法相关的例子:

$changeLink = $myRow->site_url;
  if(substr($changeLink, 0, 7) != 'http://') {
     $changeLink = 'http://' . $changeLink;  
}

// ....

echo "<a href=\"" . $changeLink . "\" target=\"_blank\"></a>";

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接