如何仅对URL字符串中的查询参数进行编码?

3

我想使用php仅对url字符串中的查询参数进行编码,如下所示的url字符串

https://torrentz-proxy.com/search?q=linux format 2015 added<6m leech>1 seed>1#12345

urlencode() 的结果是 https%3A%2F%2Ftorrentz-proxy.com%2Fsearch%3Fq%3Dlinux+format+2015+added%3C6m+leech%3E1+seed%3E1

实际上我需要的是 https://torrentz-proxy.com/search?q=linux%20format%202015%20added%3C6m%20leech%3E1%20seed%3E1#12345

怎么办呢?是否有原生的PHP函数可以做到这一点?

编辑

URL是自动生成的(不是由我生成的),示例如下

http://example.com/abc?a=1 a&b=2 b&c=3+c#123

只需在问号后面截取子字符串并对其进行编码。 - Mihai
@Mihai 然后 #(片段)会丢失吗? - linto cheeran
你不能只是对查询参数值进行URL编码吗? "https://torrentz-proxy.com/search?q=".urlencode("linux format 2015 added<6m leech>1 seed>1#12345") - gre_gor
@gre_gor 的 URL 是自动生成的(不是由我生成的),那么我该怎么做呢? - linto cheeran
你应该把那个信息放到问题中。另外,如果你的URL始终是单个q参数还是完全任意的? - gre_gor
@gre_gor 这完全是随机的,我想知道 Chrome 地址栏是如何做到这一点的。 - linto cheeran
4个回答

3
你需要解析URL,提取查询参数值,进行编码并重新构建URL。
function query_param_encode($url)
{
    $url = parse_url($url);
    $url_str = "";
    if (isset($url['scheme']))
        $url_str .= $url['scheme'].'://';
    if (isset($url['host']))
        $url_str .= $url['host'];
    if (isset($url['path']))
        $url_str .= $url['path'];
    if (isset($url['query']))
    {
        $query = explode('&', $url['query']);
        foreach ($query as $j=>$value)
        {
            $value = explode('=', $value, 2);
            if (count($value) == 2)
                $query[$j] = urlencode($value[0]).'='.urlencode($value[1]);
            else
                $query[$j] = urlencode($value[0]);
        }
        $url_str .= '?'.implode('&', $query);
    }
    if (isset($url['fragment']))
        $url_str .= '#'.$url['fragment'];

    return $url_str;
}

这将把你的URL编码为

https://torrentz-proxy.com/search?q=linux+format+2015+added%3C6m+leech%3E1+seed%3E1#12345

http://example.com/abc?a=1+a&b=2+b&c=3%2Bc#123

1
这样就可以了。
    function encodeURI($url) {
    // http://php.net/manual/en/function.rawurlencode.php
    // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/encodeURI
    $unescaped = array(
        '%2D'=>'-','%5F'=>'_','%2E'=>'.','%21'=>'!', '%7E'=>'~',
        '%2A'=>'*', '%27'=>"'", '%28'=>'(', '%29'=>')'
    );
    $reserved = array(
        '%3B'=>';','%2C'=>',','%2F'=>'/','%3F'=>'?','%3A'=>':',
        '%40'=>'@','%26'=>'&','%3D'=>'=','%2B'=>'+','%24'=>'$'
    );
    $score = array(
        '%23'=>'#'
    );
    return strtr(rawurlencode($url), array_merge($reserved,$unescaped,$score));

   }

我发现这个 链接 作为 JS 的 encodeURI() 的替代品。

0

可以使用类似这样的东西:

<?php

$url = 'https://torrentz-proxy.com/search?q=linux format 2015 added<6m leech>1 seed>1#12345';

$questPos = strpos($url, '?q');
$query = explode('#', substr($url, $questPos+3));
$encodedUrl = substr($url, 0, $questPos+3) . urlencode($query[0]);

foreach (array_slice($query, 1) as $frag) {
    $encodedUrl .= '#' . $frag;
}

var_dump($encodedUrl);

这将输出:

string(89) "https://torrentz-proxy.com/search?q=linux+format+2015+added%3C6m+leech%3E1+seed%3E1#12345"

#12345 片段丢失。 - linto cheeran
如果有多个查询参数(如q=),则返回已翻译的文本。 - linto cheeran
请检查新版本。您可以像代码中一样使用explode来处理多个?q - meysam
我认为abc.com?a=123&b=12345#abc会失败,而且URL是自动生成的(不是由我生成的),那么我该怎么做呢? - linto cheeran
1
请提供一个具备您所需要的所有功能的完整URL示例。 - meysam

0

最简单的方法是:

  • 使用explode获取基本URL
  • 仅对查询字符串进行编码(先解码以确保不会重复编码)
  • 确保将#替换为%23
$myUrl = 'https://torrentz-proxy.com/search?q=linux format 2015 added<6m leech>1 seed>1#12345';
$finalUrl = explode("?", $myUrl)[0] . "?" . urlencode(urldecode(parse_url(str_replace('#', '%23', $myUrl), PHP_URL_QUERY)))

这是一个完整的编码查询字符串:"https://torrentz-proxy.com/search?q%3Dlinux+format+2015+added%3C6m+leech%3E1+seed%3E1%2312345"

如果您愿意,可以再次将%23替换为#(根据您的问题要求)。

$finalUrl = str_replace('%23', '#', $finalUrl);

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