PHP:如何将斜杠添加到绝对 URL
Posted
技术标签:
【中文标题】PHP:如何将斜杠添加到绝对 URL【英文标题】:PHP: how to add trailing slash to absolute URL 【发布时间】:2011-07-23 19:41:45 【问题描述】:我有一个绝对 URL 列表。我需要确保它们都有斜杠,如果适用的话。所以:
http://www.domain.com/ http://www.domain.com http://www.domain.com/index.php http://www.domain.com/?message=hello我猜我需要使用正则表达式,但匹配 URL 很麻烦。希望有一个更简单的解决方案。想法?
【问题讨论】:
所以你宁愿URL路径不为空,对吧?http://www.domain.com?message=hello
呢?
@Gumbo - 我不确定你的意思。
@Kobi - 好点。我想问号之前应该有一个斜线。
@***Newbie:路径就在权限之后(即主机名www.domain.com
)和可选查询或片段之前。
【参考方案1】:
您可以使用parse_url()
来执行此操作,而不是使用正则表达式执行此操作。
例如:
$url = parse_url("http://www.example.com/ab/abc.html?a=b#xyz");
if(!isset($url['path'])) $url['path'] = '/';
$surl = $url['scheme']."://".$url['host'].$url['path'].'?'.$url['query'].'#'.$url['fragment'];
echo $surl;
【讨论】:
@Pekka 正则表达式有什么问题?您无法确定 parse_url 是否在内部使用它。尤其是当它解析比单斜杠更多的东西时。 @Col - 好吧,在这种情况下,OP 专门要求使用非正则表达式解决方案。在更一般的情况下,最好的答案总是“它取决于”,尽管 URL 往往比(\w+\.)\w+
更复杂...实际上,我并没有很快理解这个问题的基础,为什么还要加上斜线?
@Col 我倾向于总是选择标准的 URL 解析函数而不是正则表达式,因为 1.) 作为标准函数,它们应该处理所有可以想象的边缘情况和 2.) 如果你使用正则表达式会降低可维护性,或者同事,都不是很擅长这些(比如我)。不过,一般来说,正则表达式没有错。您是否看到此解决方案不起作用的情况?如果是,你能展示一下吗?没看到
@Kobi:我需要“规范化”我的网址。请记住,"domain.com" !== "domain.com" 在进行字符串比较时。但是,我需要一个唯一的 URL 列表,其中“domain.com”被认为等于“domain.com”。我想实现这一点的最佳方法是确保它们都有斜线。
@Kobi 那又怎样?当我必须在“OP 询问”和常识之间做出选择时,我总是选择后者。【参考方案2】:
这可能不是最优雅的解决方案,但它就像一个魅力。首先我们得到完整的 url,然后检查它是否有一个斜杠。如果没有,请检查是否没有查询字符串,它不是实际文件,也不是实际目录。如果 url 满足所有这些条件,我们会执行 301 重定向并添加尾部斜杠。
如果您不熟悉 PHP 标头...请注意,在此代码之前不能有任何输出 - 甚至没有空格。
$url = $_SERVER['REQUEST_URI'];
$lastchar = substr( $url, -1 );
if ( $lastchar != '/' ):
if ( !$_SERVER['QUERY_STRING'] and !is_file( $_SERVER['DOCUMENT_ROOT'].$url ) and !is_dir( $_SERVER['DOCUMENT_ROOT'].$url ) ):
header("HTTP/1.1 301 Moved Permanently");
header( "Location: $url/" );
endif;
endif;
【讨论】:
是的。我不知道完全重定向用户是非常必要的。这有可能导致无限循环——如果客户端出于某种原因取消了尾部斜线怎么办?使用substr
的做法很好,但您应该将斜杠放在脚本中需要它的任何变量上,而不是重定向用户。【参考方案3】:
对于这个非常具体的问题,完全不使用正则表达式也可能是一种选择。如果您的列表很长(几千个 URL)并且时间很重要,您可以选择手动编码这个非常简单的操作。
这将做同样的事情:
$str .= (substr($str, -1) == '/' ? '' : '/');
当然远不如像正则表达式那样优雅或灵活,但它避免了解析正则表达式字符串的开销,并且运行速度与 PHP 能够做到的一样快。 可以说它比正则表达式可读性差,但这取决于读者对正则表达式语法的舒适程度(有些人可能会觉得它更具可读性)。
它肯定不会检查字符串是否真的是格式正确的 URL(例如 zerkms 的正则表达式),但你已经知道你的字符串无论如何都是 URL,所以这有点多余。
不过,如果您的列表包含 10 或 20 个 URL,请忘记这篇文章。使用正则表达式,差异为零。
【讨论】:
$str = rtrim($string, '/') 。 '/'; +1 表示此处不进行正则表达式。 “它当然不像正则表达式那样优雅或灵活。” ——不,不,恰恰相反!下意识的preg_...
调用像这样的简单任务与优雅完全相反。顺便说一句,谈到优雅:@Vino 的“smartlet”可能是这个页面上最酷的东西,干得好! :)
请注意,这不会规范带有多个尾随斜杠的草率 URL。 (我看到 OP 在接受的答案下的评论中提到规范化是一项要求;无论如何,这都是一个不错的选择。)@Vino 会的。 (这应该是一个单独的答案,并且被接受。)【参考方案4】:
$url = 'http://www.domain.com';
$need_to_add_trailing_slash = preg_match('~^https?://[^/]+$~', $url);
【讨论】:
你也可以这样做:$url = preg_replace("~^https?://[^/]+$~", "$0/", $url);
【参考方案5】:
试试这个:
if (!preg_match("/.*\/$/", $url))
$url = "$url" . "/";
【讨论】:
.*
是多余的,如果你选择不同的分隔符,你可以避免转义/
以上是关于PHP:如何将斜杠添加到绝对 URL的主要内容,如果未能解决你的问题,请参考以下文章
如何禁用 301 重定向,在 Apache 中将斜杠添加到目录名称