Php 当URL中不存在参数时,如何去掉“?”?

Php 当URL中不存在参数时,如何去掉“?”?,php,Php,我有以下规则检查url是否包含以p2开头的任何参数: function unparse_url($parsed_url) { $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : ''; $host = isset($parsed_url['host']) ? $parsed_url['host'] : ''; $port = isset($parsed_url['port

我有以下规则检查url是否包含以
p2
开头的任何参数:

function unparse_url($parsed_url) {
  $scheme   = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
  $host     = isset($parsed_url['host']) ? $parsed_url['host'] : '';
  $port     = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
  $user     = isset($parsed_url['user']) ? $parsed_url['user'] : '';
  $pass     = isset($parsed_url['pass']) ? ':' . $parsed_url['pass']  : '';
  $pass     = ($user || $pass) ? "$pass@" : '';
  $path     = isset($parsed_url['path']) ? $parsed_url['path'] : '';
  $query    = isset($parsed_url['query']) ? '?' . trim($parsed_url['query'], '&') : '';
  $fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
  return "$scheme$user$pass$host$port$path$query$fragment";
}

function strip_query($url, $query_to_strip) {
  $parsed = parse_url($url);
  $parsed['query'] = preg_replace('/(^|&)'.$query_to_strip.'[^&]*/', '', $parsed['query']);
  return unparse_url($parsed);
}

$url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

$new_url = (strip_query($url, 'p2'));

# redirect  if url contains anything that starts with p2 

$filtered = array_filter(array_keys($_GET), function($k) {
    return strpos($k, 'p2') === 0;
});

if ( !empty($filtered) ) {
    header ("Location: $new_url");
}
else {

}
如果url包含任何
p2*
参数,将重定向到没有这些参数的同一页面

例如:

<?php

function removeQuery($url, $param) {
    $parsed = parse_url($url);
    parse_str($parsed['query'], $query);

    unset($query[$param]);

    $parsed['scheme'] .= '://';
    $parsed['query'] = http_build_query($query);
    if (!empty($parsed['query']))
        $parsed['path'] .= '?';

    return implode($parsed);
}

echo removeQuery('http://domain.com/?a=3&p2=1', 'a') . "\n";
echo removeQuery('http://domain.com/?a=3&p2=1', 'p2') . "\n";
echo removeQuery('http://domain.com/?p2=1', 'p2');
domain.com/?a=3&p2=1

将重定向到

domain.com/?a=3

但是,根据当前规则,如果原始URL为:

domain.com/?p2=1

然后它将重定向到:

domain.com/?

但由于它毫无意义,我希望在这种情况下,它将重定向到:

domain.com/


如何做到这一点?

如果可用,这可以在没有php代码的情况下完成。

像@dontfight一样,我建议使用mod_rewrite,但如果您喜欢php,可以在执行重定向之前使用

rtrim($url, '?');
用你的代码你可以像这样使用

$filtered = array_filter(array_keys($_GET), function($k) {
    return strpos($k, 'p2') === 0;
});

$new_url_trim = rtrim($new_url, '?');

if ( !empty($filtered) ) {
    header ("Location: $new_url_trim");
}
else {

}

下面是删除查询参数的另一种方法:

  • 解析URL以将其分为方案、路径和查询
  • 将查询字符串解析为数组
  • 取消设置数组中的参数
  • 重新创建URL
  • 例如:

    <?php
    
    function removeQuery($url, $param) {
        $parsed = parse_url($url);
        parse_str($parsed['query'], $query);
    
        unset($query[$param]);
    
        $parsed['scheme'] .= '://';
        $parsed['query'] = http_build_query($query);
        if (!empty($parsed['query']))
            $parsed['path'] .= '?';
    
        return implode($parsed);
    }
    
    echo removeQuery('http://domain.com/?a=3&p2=1', 'a') . "\n";
    echo removeQuery('http://domain.com/?a=3&p2=1', 'p2') . "\n";
    echo removeQuery('http://domain.com/?p2=1', 'p2');
    

    我还注意到,如果p2出现在字符串中的任何位置,您希望将其删除,因此这里有另一个版本专门用于此目的:

    <?php
    
    function removeP2($url) {
        $parsed = parse_url($url);
        parse_str($parsed['query'], $query);
    
        foreach ($query as $key => $value)
            if (strpos($key, 'p2') === 0)
                unset($query[$key]);
    
        $parsed['scheme'] .= '://';
        $parsed['query'] = http_build_query($query);
        if (!empty($parsed['query']))
            $parsed['path'] .= '?';
    
        return implode($parsed);
    }
    
    echo removeP2('http://domain.com/?a=3&p2=1') . "\n";
    echo removeP2('http://domain.com/?a=3&p2sks=1') . "\n";
    echo removeP2('http://domain.com/?p2=1');
    

    现在要使其重定向,您已经知道如何重定向:

    header("Location: " . removeP2('http://' . $_SERVER[HTTP_HOST] . $_SERVER[REQUEST_URI]));
    

    既然没人费心告诉你出了什么事

    您的问题是
    strip\u query()
    函数始终将
    $url[“query”]
    设置为一个值,即使该值是空字符串:

    $parsed['query'] = preg_replace('/(^|&)'.$query_to_strip.'[^&]*/', '', $parsed['query']);
    
    $query    = !empty($parsed_url['query']) ? '?' . trim($parsed_url['query'], '&') : '';
    
    unparse_url()
    函数获取url时,它将使用
    isset()
    检查数组索引,该索引始终通过:

    $query    = isset($parsed_url['query']) ? '?' . trim($parsed_url['query'], '&') : '';
    
    您可以使用
    empty()
    ,而不是使用
    isset()
    进行检查,如果值未设置或为空字符串,则返回false:

    $parsed['query'] = preg_replace('/(^|&)'.$query_to_strip.'[^&]*/', '', $parsed['query']);
    
    $query    = !empty($parsed_url['query']) ? '?' . trim($parsed_url['query'], '&') : '';
    

    这不是一个答案,这是一个评论,但它有点长

    为什么您如此热衷于从URL中删除此变量?你必须竭尽全力根除它的存在,这对你造成了什么伤害?为什么不

    unset($_GET['p2']);
    
    但既然没有意义,

    以什么方式

    我可以在
    unparsed\u url($parsed\u url)
    函数中看到一些优点,如果您修复了错误(提示:尝试使用用户名和/或密码的测试用例)那么它的结构就相当好了——但是随后用于操作数据的代码是一个混乱的正则表达式字符串拼接的混合体——这不是处理这种结构化数据的正确方法——PHP有相应的函数

    但最糟糕的是注入另一个完整的RTT来解析URL


    你比这个摇滚乐棒多了

    我不想使用
    htaccess
    ,因为我计划将
    p2
    参数的数据存储在会话中。仅供参考:。
    htaccess
    没有修改。信息技术当您无法访问服务器配置时,这是apache在运行时设置某些内容的方法。但是如果可以,则不需要
    .htaccess
    如果不需要,我可以使用
    mod_rewrite
    并同时将
    p2
    参数最初包含的数据存储在会话中吗?有人能回答这个子问题吗?我认为这是不可能的,由于mod_rewrite来自Apache,session来自PHP。我当然希望保留
    ,以防原始url包含其他参数,例如在
    domain.com/?a=3&p2=1
    的情况下,它会保留它吗?@rockyraw与rtrim一起它会删除该参数吗?马克,如果它是最后一个字符:)你让我有点迷路了,基本上我不想回显新的url,我想重定向到它。代码不能包含对
    domain.com
    的任何引用,它需要独立,因此我使用
    http://$\u服务器[http\u主机]$\u服务器[REQUEST\u URI]
    我为您提供了一个转换URL的函数<代码>标题(“位置:”.removeP2(“http://$\u服务器[http\u主机]$\u服务器[REQUEST\u URI]”)。只需在函数中插入独立的url,就可以在不使用P2的情况下返回url,然后可以重定向到它。好的,谢谢,这也很有效。使用你的代码更好吗?仅仅因为它更整洁?或者它还会有更好的服务器性能?最终结果有什么不同吗?看看原始代码,看起来你考虑了很多。但是,服务器没有检测到片段,因此不需要检查它是否为空。所以它会更快,因为我完全忽略了片段,但只有基准测试才能证实这一点。最终结果应该没有差别(除非涉及到碎片)。你是说?我需要检查一下。它比使用我的代码有什么优势呢?哈哈,我只是想让url看起来更自然。我并没有提出这个代码,我只是根据我在这里提出的各种问题来构建它。我不是php开发人员(因此我不确定什么是
    unset
    ,但请注意,这需要处理以
    p2
    开头的任何参数,比如
    p2\u hello
    )。我唯一的目标是能够从url中剥离参数,首先将它们存储在会话中,然后通过重定向在客户端销毁证据。