2009-08-09 18 views
76

Tengo una cadena con una URL completa que incluye variables GET. ¿Cuál es la mejor manera de eliminar las variables GET? ¿Hay alguna buena manera de eliminar solo uno de ellos?¿Una forma hermosa de eliminar variables GET con PHP?

Se trata de un código que funciona, pero no es muy bonito (creo):

$current_url = explode('?', $current_url); 
echo $current_url[0]; 

El código anterior sólo elimina todas las variables GET. En mi caso, la URL se genera desde un CMS, por lo que no necesito información sobre las variables del servidor.

+1

Me quedaría con lo que tienes a menos que el rendimiento no sea un problema. La solución de expresiones regulares proporcionada por Gumbo va a ser lo más bonita posible. – MitMaro

+0

No tiene que ser hermoso si va en functions.php o donde ocultes tus feos bits, solo necesitarás ver qs_build() para llamarlo –

+0

Esta es una forma de hacerlo a través de una buena función anónima. http://stackoverflow.com/questions/4937478/strip-off-url-parameter-with-php/17287657#17287657 – doublejosh

Respuesta

196

Ok, para eliminar todas las variables, tal vez el más bonito es

$url = strtok($url, '?'); 

Ver sobre strtok here.

Es el más rápido (ver a continuación), y maneja las URL sin un '?' correctamente.

Para tomar una url + cadena de consulta y quitar una sola variable (sin necesidad de utilizar una expresión regular sustituir, que puede ser más rápido en algunos casos), es posible hacer algo como:

function removeqsvar($url, $varname) { 
    list($urlpart, $qspart) = array_pad(explode('?', $url), 2, ''); 
    parse_str($qspart, $qsvars); 
    @unset($qsvars[$varname]); 
    $newqs = http_build_query($qsvars); 
    return $urlpart . '?' . $newqs; 
} 

una expresión regular reemplazar para eliminar una var sola podría ser:

function removeqsvar($url, $varname) { 
    return preg_replace('/([?&])'.$varname.'=[^&]+(&|$)/','$1',$url); 
} 

Heres los horarios de algunos métodos diferentes, garantizando el tiempo se restablece entre medio de carreras.

<?php 

$number_of_tests = 40000; 

$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$starttime = $mtime; 

for($i = 0; $i < $number_of_tests; $i++){ 
    $str = "http://www.example.com?test=test"; 
    preg_replace('/\\?.*/', '', $str); 
} 
$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$endtime = $mtime; 
$totaltime = ($endtime - $starttime); 
echo "regexp execution time: ".$totaltime." seconds; "; 

$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$starttime = $mtime; 
for($i = 0; $i < $number_of_tests; $i++){ 
    $str = "http://www.example.com?test=test"; 
    $str = explode('?', $str); 
} 
$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$endtime = $mtime; 
$totaltime = ($endtime - $starttime); 
echo "explode execution time: ".$totaltime." seconds; "; 

$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$starttime = $mtime; 
for($i = 0; $i < $number_of_tests; $i++){ 
    $str = "http://www.example.com?test=test"; 
    $qPos = strpos($str, "?"); 
    $url_without_query_string = substr($str, 0, $qPos); 
} 
$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$endtime = $mtime; 
$totaltime = ($endtime - $starttime); 
echo "strpos execution time: ".$totaltime." seconds; "; 

$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$starttime = $mtime; 
for($i = 0; $i < $number_of_tests; $i++){ 
    $str = "http://www.example.com?test=test"; 
    $url_without_query_string = strtok($str, '?'); 
} 
$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$endtime = $mtime; 
$totaltime = ($endtime - $starttime); 
echo "tok execution time: ".$totaltime." seconds; "; 

muestra

regexp execution time: 0.14604902267456 seconds; explode execution time: 0.068033933639526 seconds; strpos execution time: 0.064775943756104 seconds; tok execution time: 0.045819044113159 seconds; 
regexp execution time: 0.1408839225769 seconds; explode execution time: 0.06751012802124 seconds; strpos execution time: 0.064877986907959 seconds; tok execution time: 0.047760963439941 seconds; 
regexp execution time: 0.14162802696228 seconds; explode execution time: 0.065848112106323 seconds; strpos execution time: 0.064821004867554 seconds; tok execution time: 0.041788101196289 seconds; 
regexp execution time: 0.14043688774109 seconds; explode execution time: 0.066350221633911 seconds; strpos execution time: 0.066242933273315 seconds; tok execution time: 0.041517972946167 seconds; 
regexp execution time: 0.14228296279907 seconds; explode execution time: 0.06665301322937 seconds; strpos execution time: 0.063700199127197 seconds; tok execution time: 0.041836977005005 seconds; 

victorias strtok, y es, con mucho, el código más pequeño.

+0

Ok, cambié de opinión. strtok way se ve aún mejor. Las otras funciones no funcionaron tan bien. Probé las funciones en estas variables get? Cbyear = 2013 & test = value y escribí echo removeqsvar ($ current_url, 'cbyear'); y obtuve el resultado: amp; test = value –

+0

ah sí ... la expresión regular no está completa - tendrá que reemplazar el delimitador final y perder el de la izquierda (lo escribió a ciegas). La función más larga todavía debería funcionar bien. preg_replace ('/([?&])'.$ varname.' = [^ &] + (& | $)/',' $ 1 ', $ url) debería funcionar – Justin

+2

+1 para 'strtok', nadie más pensó de eso :) – knittl

2

Puede usar el server variables para esto, por ejemplo $_SERVER['REQUEST_URI'], o mejor aún: $_SERVER['PHP_SELF'].

+3

Esto supone, por supuesto, que la URL que está analizando es la página que realiza el análisis sintáctico. – MitMaro

26

¿Qué tal:

preg_replace('/\\?.*/', '', $str) 
+1

Definitivamente más bonito. Me pregunto cuál funcionaría mejor sin embargo. +1 – MitMaro

+0

Esto me salvó algunas filas y para mí esto es corto y hermoso. ¡Gracias! –

+0

Todavía vale la pena un voto popular; la solución más corta. – Scharrels

7

Si la dirección URL que está tratando de eliminar la cadena de consulta de la URL actual es el del script PHP, puede utilizar uno de los métodos mencionados anteriormente. Si solo tiene una variable de cadena con una URL y desea quitar todo lo que pasa después del '?' que puede hacer:

$pos = strpos($url, "?"); 
$url = substr($url, 0, $pos); 
+0

+1 porque es la única respuesta aquí que responde la pregunta y proporciona una alternativa. – MitMaro

+1

Debería considerar que la URL podría no contener un '?'. Su código luego devolverá una cadena vacía. – Gumbo

0

¿Qué tal una función para reescribir la cadena de consulta haciendo un bucle a través de la matriz $ _GET

! esbozo de una función adecuada

function query_string_exclude($exclude, $subject = $_GET, $array_prefix=''){ 
    $query_params = array; 
    foreach($subject as $key=>$var){ 
     if(!in_array($key,$exclude)){ 
     if(is_array($var)){ //recursive call into sub array 
      $query_params[] = query_string_exclude($exclude, $var, $array_prefix.'['.$key.']'); 
     }else{ 
      $query_params[] = (!empty($array_prefix)?$array_prefix.'['.$key.']':$key).'='.$var; 
     } 
     } 
    } 

    return implode('&',$query_params); 
} 

Algo como esto sería bueno tener a mano para los enlaces de paginación etc.

<a href="?p=3&<?= query_string_exclude(array('p')) ?>" title="Click for page 3">Page 3</a> 
7

Inspirado por el comentario de @MitMaro, escribí un pequeño punto de referencia para probar la velocidad de soluciones de @Gumbo, @ Matt Bridges y @justin la propuesta en la pregunta:

function teststrtok($number_of_tests){ 
    for($i = 0; $i < $number_of_tests; $i++){ 
     $str = "http://www.example.com?test=test"; 
     $str = strtok($str,'?'); 
    } 
} 
function testexplode($number_of_tests){ 
    for($i = 0; $i < $number_of_tests; $i++){ 
     $str = "http://www.example.com?test=test"; 
     $str = explode('?', $str); 
    } 
} 
function testregexp($number_of_tests){ 
    for($i = 0; $i < $number_of_tests; $i++){ 
     $str = "http://www.example.com?test=test"; 
     preg_replace('/\\?.*/', '', $str); 
    } 
} 
function teststrpos($number_of_tests){ 
    for($i = 0; $i < $number_of_tests; $i++){ 
     $str = "http://www.example.com?test=test"; 
     $qPos = strpos($str, "?"); 
     $url_without_query_string = substr($str, 0, $qPos); 
    } 
} 

$number_of_runs = 10; 
for($runs = 0; $runs < $number_of_runs; $runs++){ 

    $number_of_tests = 40000; 
    $functions = array("strtok", "explode", "regexp", "strpos"); 
    foreach($functions as $func){ 
    $starttime = microtime(true); 
    call_user_func("test".$func, $number_of_tests); 
    echo $func.": ". sprintf("%0.2f",microtime(true) - $starttime).";"; 
    } 
    echo "<br />"; 
} 
 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 

Res ult: el strtok de @ justin es el más rápido.

Nota: probado en un sistema local Debian Lenny con Apache2 y PHP5.

+0

tiempo de ejecución de expresiones regulares: 0.14591598510742 segundos; tiempo de ejecución de explosión: 0.07137393951416 segundos; tiempo de ejecución strpos: 0.080883026123047 segundos; tiempo de ejecución de tok: 0.042459011077881 segundos; – Justin

+0

¡Muy bonito! Creo que la velocidad es importante. No es lo único que va a suceder. Una aplicación web podría tener cientos de funciones. "Todo está en los detalles". Gracias, vota! –

+0

Justin, gracias.El script ahora está limpio y toma su solución en cuenta. – Scharrels

0
@list($url) = explode("?", $url, 2); 
2

¿No pudo usar las variables del servidor para hacer esto?

funcionaría esto ?:

unset($_GET['page']); 
$url = $_SERVER['SCRIPT_NAME'] ."?".http_build_query($_GET); 

Es sólo una idea

O.

0

basename($_SERVER['REQUEST_URI']) devuelve todo lo que después e incluyendo el '?',

En mi código a veces necesito sólo las secciones, por lo que la separan a cabo para que pueda obtener el valor de lo que necesito sobre la marcha. No estoy seguro de la velocidad de rendimiento en comparación con otros métodos, pero es realmente útil para mí.

$urlprotocol = 'http'; if ($_SERVER["HTTPS"] == "on") {$urlprotocol .= "s";} $urlprotocol .= "://"; 
$urldomain = $_SERVER["SERVER_NAME"]; 
$urluri = $_SERVER['REQUEST_URI']; 
$urlvars = basename($urluri); 
$urlpath = str_replace($urlvars,"",$urluri); 

$urlfull = $urlprotocol . $urldomain . $urlpath . $urlvars; 
5

Otra solución ... ¿Encuentro esta función más elegante, también eliminará el rastro '?' si la clave para eliminar es la única en la cadena de consulta.

/** 
* Remove a query string parameter from an URL. 
* 
* @param string $url 
* @param string $varname 
* 
* @return string 
*/ 
function removeQueryStringParameter($url, $varname) 
{ 
    $parsedUrl = parse_url($url); 
    $query = array(); 

    if (isset($parsedUrl['query'])) { 
     parse_str($parsedUrl['query'], $query); 
     unset($query[$varname]); 
    } 

    $path = isset($parsedUrl['path']) ? $parsedUrl['path'] : ''; 
    $query = !empty($query) ? '?'. http_build_query($query) : ''; 

    return $parsedUrl['scheme']. '://'. $parsedUrl['host']. $path. $query; 
} 

Pruebas:

$urls = array(
    'http://www.example.com?test=test', 
    'http://www.example.com?bar=foo&test=test2&foo2=dooh', 
    'http://www.example.com', 
    'http://www.example.com?foo=bar', 
    'http://www.example.com/test/no-empty-path/?foo=bar&test=test5', 
    'https://www.example.com/test/test.test?test=test6', 
); 

foreach ($urls as $url) { 
    echo $url. '<br/>'; 
    echo removeQueryStringParameter($url, 'test'). '<br/><br/>'; 
} 

seria:

http://www.example.com?test=test 
http://www.example.com 

http://www.example.com?bar=foo&test=test2&foo2=dooh 
http://www.example.com?bar=foo&foo2=dooh 

http://www.example.com 
http://www.example.com 

http://www.example.com?foo=bar 
http://www.example.com?foo=bar 

http://www.example.com/test/no-empty-path/?foo=bar&test=test5 
http://www.example.com/test/no-empty-path/?foo=bar 

https://www.example.com/test/test.test?test=test6 
https://www.example.com/test/test.test 

» Run these tests on 3v4l

0

En mi opinión, la mejor manera sería la siguiente:

<? if(isset($_GET['i'])){unset($_GET['i']); header('location:/');} ?> 

Comprueba si hay un parámetro 'i' GET y lo elimina si lo hay.

Cuestiones relacionadas