Манипуляция строк запроса PHP

У кого-нибудь есть конечная функция (ы) PHP для добавления / удаления параметров из строки запроса? Он должен обрабатывать все возможные случаи, но я видел те, которые обрабатывают некоторые случаи, но не все.

Некоторые примеры:

  • http://mysite.com?param1=1&param2=2
  • http://www.mysite.com/?param1[]=1&param1[]=2
  • FTP: // пользователь: pass@mysite.com/files/uploads/ param1 = 1 & param2 = 2
  • /? Param1 = 1 & param2 = 2
  • /page.html?param1=1
  • /dir/page.html?test=1&bla=2
  • /dir/page.html?param1=1#jump_to_bottom

В идеале это должно быть примерно так:

function add_get_param($uri, $name, $value = null) { ... } function remove_get_param($uri, $name) { ... } 

Некоторые примеры тестов:

 $var = add_get_param('http://mysite.com?param1=1&param2=2', 'param3', 3); // http://mysite.com?param1=1&param2=2&param3=3 

а также:

 $var = add_get_param('/dir/page.html?param1=1&param2=2#jump_to_bottom', 'param3'); // /dir/page.html?param1=1&param2=2&param3#jump_to_bottom 

и т.д…

Хорошо, я написал свои собственные функции:

PHP: http://pastebin.org/170157 jQuery: http://pastebin.org/169981

попробуйте встроенные функции http_build_query и parse_str , они используют ассоциативные массивы в том же стиле, что и $_GET как промежуточные, но, похоже, делают то, что вы хотите …

Я не знаю о конечном решении. Но у PHP есть несколько очень полезных родных функций, которые делают вашу собственную определенную функцию более простой.

Проверьте: html_build_query () , parse_str () и p arse_url ()

Это эскиз функции, с которой вы можете начать:

 function add_get_param($url, $param, $value) { $parts_url = parse_url($url); parse_str($parts_url['query'], $parts_query); $parts_query[$param] = $value; return $parts_url['scheme'] . '://' . $parts_url['host'] . '/' . $parts_url['path'] . '?' . http_build_query($parts_query); } var_dump(add_get_param('http://mysite.com?param1=1&param2=2', 'param3', 3)); 

UPD : поскольку parse_str разбивает данные (заменяет точки parse_str подчеркивания), я не думаю, что этот эскиз полезен.

Хорошо, что я написал свой собственный, основанный на эскизе zerkms

 class URL { public static function each_get($url, $each_callback = null, $last_callback = null) { $url = parse_url($url); $result = ''; if (isset($url['scheme'])) $result .= $url['scheme'].'://'; if (isset($url['user'])) { $result .= $url['user']; if (isset($url['pass'])) $result .= ':'.$url['pass']; $result .= '@'; } if (isset($url['host'])) $result .= $url['host']; if (isset($url['path'])) $result .= $url['path']; if (!isset($url['query'])) $url['query'] = ''; $query = array(); $callable = is_callable($each_callback); foreach (explode('&', $url['query']) as $param) { if ($param == '') { continue; } if (!$callable) { $query[] = $param; continue; } $callback_result = $each_callback($param); if ($callback_result === true) { $query[] = $param; } elseif ($callback_result !== false) { $query[] = $callback_result; } } if (is_callable($last_callback)) { $query = $last_callback($query); } $query = implode('&', $query); $result .= strlen($query) ? '?'.$query : ''; if (isset($url['fragment'])) $result .= '#'.$url['fragment']; return $result; } public static function add_get($url, $new_param, $new_value = null) { return static::each_get($url, function($param) { $param = explode('=', $param); if (isset($param[1])) { return $param[0].'='.$param[1]; } return $param[0]; }, function($query) use($new_param, $new_value) { if ($new_value === null) { $query[] = $new_param; } else { $query[] = $new_param.'='.$new_value; } return $query; }); } public static function remove_get($url, $remove_param) { return static::each_get($url, function($param) use($remove_param) { $param = explode('=', $param); return $param[0] != $remove_param; }); } public static function replace_get($url, $name, $value = null) { return static::add_get(static::remove_get($url, $name), $name, $value); } } 

И вот мои ограниченные тестовые примеры:

 function test($test, $result) { static $i; $i++; if ($test !== $result) { echo $i.' Fail: got '.$test.' should be '.PHP_EOL.' '.$result.'<br>'.PHP_EOL; } else { echo $i.' Pass: '.$test.'<br>'.PHP_EOL; } } $urls = array( 0 => 'http://user:pass@www.site.com?a=1', 1 => 'http://www.site.com?a=1', 2 => '/dir/page.php?a=1', 3 => '/dir/?a=1', 4 => '/dir?a=1', 5 => '/?a=1', 6 => '?a=1', 7 => 'http://user:pass@www.site.com?a=1#hash', 8 => 'http://www.site.com?a=1#hash', 9 => '/dir/page.php?a=1#hash', 10 => '/dir/?a=1#hash', 11 => '/dir?a=1#hash', 12 => '/?a=1#hash', 13 => '?a=1#hash', 14 => 'http://www.site.com/?a=1', 15 => 'http://www.site.com/?a=1#hash', 16 => '/dir/page.php?a=1&b=2&c=3', ); test(URL::add_get($urls[0], 'b', 2), 'http://user:pass@www.site.com?a=1&b=2'); test(URL::add_get($urls[1], 'b', 2), 'http://www.site.com?a=1&b=2'); test(URL::add_get($urls[2], 'b', 2), '/dir/page.php?a=1&b=2'); test(URL::add_get($urls[3], 'b', 2), '/dir/?a=1&b=2'); test(URL::add_get($urls[4], 'b', 2), '/dir?a=1&b=2'); test(URL::add_get($urls[5], 'b', 2), '/?a=1&b=2'); test(URL::add_get($urls[6], 'b', 2), '?a=1&b=2'); test(URL::add_get($urls[7], 'b', 2), 'http://user:pass@www.site.com?a=1&b=2#hash'); test(URL::add_get($urls[8], 'b', 2), 'http://www.site.com?a=1&b=2#hash'); test(URL::add_get($urls[9], 'b', 2), '/dir/page.php?a=1&b=2#hash'); test(URL::add_get($urls[10], 'b'), '/dir/?a=1&b#hash'); test(URL::add_get($urls[11], 'berLongBla 1235_+'), '/dir?a=1&berLongBla 1235_+#hash'); test(URL::add_get($urls[12], 'a', 2), '/?a=1&a=2#hash'); test(URL::add_get($urls[13], 'a[]', 2), '?a=1&a[]=2#hash'); test(URL::add_get($urls[14], 'b', 2), 'http://www.site.com/?a=1&b=2'); test(URL::add_get($urls[15], 'b', 2), 'http://www.site.com/?a=1&b=2#hash'); test(URL::remove_get($urls[0], 'a'), 'http://user:pass@www.site.com'); test(URL::remove_get($urls[1], 'a'), 'http://www.site.com'); test(URL::remove_get($urls[2], 'a'), '/dir/page.php'); test(URL::remove_get($urls[3], 'a'), '/dir/'); test(URL::remove_get($urls[4], 'a'), '/dir'); test(URL::remove_get($urls[5], 'a'), '/'); test(URL::remove_get($urls[6], 'a'), ''); test(URL::remove_get($urls[16], 'b'), '/dir/page.php?a=1&c=3'); 

Я также преобразовал его в JavaScript / jQuery

 URL = {}; URL.parse_url = function(str, component) { var o = { strictMode: false, key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], q: { name: "queryKey", parser: /(?:^|&)([^&=]*)=?([^&]*)/g }, parser: { strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/\/?)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // Added one optional slash to post-protocol to catch file:/// (should restrict this) } }; var m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), uri = {}, i = 14; while (i--) {uri[o.key[i]] = m[i] || "";} switch (component) { case 'PHP_URL_SCHEME': return uri.protocol; case 'PHP_URL_HOST': return uri.host; case 'PHP_URL_PORT': return uri.port; case 'PHP_URL_USER': return uri.user; case 'PHP_URL_PASS': return uri.password; case 'PHP_URL_PATH': return uri.path; case 'PHP_URL_QUERY': return uri.query; case 'PHP_URL_FRAGMENT': return uri.anchor; default: var retArr = {}; if (uri.protocol !== '') {retArr.scheme=uri.protocol;} if (uri.host !== '') {retArr.host=uri.host;} if (uri.port !== '') {retArr.port=uri.port;} if (uri.user !== '') {retArr.user=uri.user;} if (uri.password !== '') {retArr.pass=uri.password;} if (uri.path !== '') {retArr.path=uri.path;} if (uri.query !== '') {retArr.query=uri.query;} if (uri.anchor !== '') {retArr.fragment=uri.anchor;} return retArr; } } URL.each_get = function(url, each_callback, last_callback) { url = URL.parse_url(url); var result = ''; if (url.scheme) result += url.scheme+'://'; if (url.user) { result += url.user; if (url.pass) result += ':'+url.pass; result += '@'; } if (url.host) result += url.host; if (url.path) result += url.path; if (!url.query) url.query = ''; var query = []; $.each(url.query.split('&'), function(key, param) { if (param == '') { return; } if (!each_callback) { query.push(param); return; } var callback_result = each_callback(param); if (callback_result === true) { query.push(param); } else if (callback_result !== false) { query.push(callback_result); } }); if (last_callback) { query = last_callback(query); } query = query.join('&'); result += query.length ? '?'+query : ''; if (url.fragment) result += '#'+url.fragment; return result; } URL.add_get = function(url, new_param, new_value) { return URL.each_get(url, function(param) { param = param.split('='); if (typeof param[1] != 'undefined') { return param[0]+'='+param[1]; } return param[0]; }, function(query) { if (typeof new_value == 'undefined') { query.push(new_param); } else { query.push(new_param+'='+new_value); } return query; }); } URL.remove_get = function(url, remove_param) { return URL.each_get(url, function(param) { param = param.split('='); return param[0] != remove_param; }); } URL.replace_get = function(url, name, value) { return URL.add_get(URL.remove_get(url, name), name, value); } var i = 0; function test(test, result) { i++; if (test !== result) { console.debug(i+' Fail: got '+test+' should be '+result); } else { console.debug(i+' Pass: '+test); } } 

И ограниченные текстовые случаи:

 var urls = { 0 : 'http://user:pass@www.site.com?a=1', 1 : 'http://www.site.com?a=1', 2 : '/dir/page.php?a=1', 3 : '/dir/?a=1', 4 : '/dir?a=1', 5 : '/?a=1', 6 : '?a=1', 7 : 'http://user:pass@www.site.com?a=1#hash', 8 : 'http://www.site.com?a=1#hash', 9 : '/dir/page.php?a=1#hash', 10 : '/dir/?a=1#hash', 11 : '/dir?a=1#hash', 12 : '/?a=1#hash', 13 : '?a=1#hash', 14 : 'http://www.site.com/?a=1', 15 : 'http://www.site.com/?a=1#hash', 16 : '/dir/page.php?a=1&b=2&c=3' }; test(URL.add_get(urls[0], 'b', 2), 'http://user:pass@www.site.com?a=1&b=2'); test(URL.add_get(urls[1], 'b', 2), 'http://www.site.com?a=1&b=2'); test(URL.add_get(urls[2], 'b', 2), '/dir/page.php?a=1&b=2'); test(URL.add_get(urls[3], 'b', 2), '/dir/?a=1&b=2'); test(URL.add_get(urls[4], 'b', 2), '/dir?a=1&b=2'); test(URL.add_get(urls[5], 'b', 2), '/?a=1&b=2'); test(URL.add_get(urls[6], 'b', 2), '?a=1&b=2'); test(URL.add_get(urls[7], 'b', 2), 'http://user:pass@www.site.com?a=1&b=2#hash'); test(URL.add_get(urls[8], 'b', 2), 'http://www.site.com?a=1&b=2#hash'); test(URL.add_get(urls[9], 'b', 2), '/dir/page.php?a=1&b=2#hash'); test(URL.add_get(urls[10], 'b'), '/dir/?a=1&b#hash'); test(URL.add_get(urls[11], 'berLongBla 1235_+'), '/dir?a=1&berLongBla 1235_+#hash'); test(URL.add_get(urls[12], 'a', 2), '/?a=1&a=2#hash'); test(URL.add_get(urls[13], 'a[]', 2), '?a=1&a[]=2#hash'); test(URL.add_get(urls[14], 'b', 2), 'http://www.site.com/?a=1&b=2'); test(URL.add_get(urls[15], 'b', 2), 'http://www.site.com/?a=1&b=2#hash');