Add params to query string in a clean way in php - php

I'd like to find a clean if possibile (without too much string manipulation preg_*)
I know that to replace a parameter I would do
$_GET['info'] = "newinfo";
and to remove a parameter:
unset($_GET['info']);
so is there something like that that I can use?
of course after I've "unset" or "set" I'm building a new query.
(http_build_query).
At the end I'm trying to make this:
/index.php?foo=bar
to
/index.php?foo=bar&info=newinfo

Just do this:
$get = $_GET;
$get['new'] = 'some value';
function getPath()
{
// Stolen from https://stackoverflow.com/a/8775529/3578036
$request = parse_url($_SERVER['REQUEST_URI']);
$path = $request["path"];
return rtrim(str_replace(basename($_SERVER['SCRIPT_NAME']), '', $path), '/');
}
header("Location: " . getPage() . http_build_query($get));
The above code will create a query string and append it to the current URL and redirect to that location. Obviously, you can change the location that you redirect to by replacing the getPage() function result and putting your own result there, this just demonstrates the premise of the answer.
The docs for http_build_query are a very good place to start.
Effectively, what it will do is convert an associative array into an HTTP query string.

Related

Laravel: Get query params of an generated URI

On the API I'm working on, a previous request generates a link that goes like this:
https://api.example.com/example/v1/individuals?$expand=emails%2Cphones&$skip=30
I need to get this "skip" param and send the data back to my backend, to process a request on the whole link plus the skip param, that changes along with the system.
Any tip on how to get this "skip" param?
remove $ sign from query param and try $value = request('skip') to get skip value
// Your api controller
public function someMethod(Request $request)
{
$request->query('skip', 10); // returns 30 for https://api.example.com/example/v1/individuals?expand=emails%2Cphones&skip=30 or 10 if skip is not set.
}
If you received the url from 3rd API and you don't wanna change it, you can do the following:
$urlFromApi = 'https://api.example.com/example/v1/individuals?$expand=emails%2Cphones&$skip=30';
//Remember to use single quote if you wanna paste string with '$' as a character with PHP.
$url = urlencode($urlFromApi);
$parts = parse_url($url);
parse_str($parts["path"], $a);
preg_match('/%24skip\%3D(\d+)/', $parts["path"], $matches);
$skip = $matches[1];
echo $skip;

changing get variable using parse_url not working in php

I've looked at every post on SO that remotely pertains to this and I just can't figure this out. This code is taken directly from another SO post and was marked as the correct working answer:
$query = $_GET;
// replace parameter(s)
$query['d'] = 'new_value';
// rebuild url
$query_result = http_build_query($query);
// new link
Link
Again, taken straight from another post. When I try this code, i change the $_GET to the actual URL that i want to alter. When the code gets to the $query['d'] part, it tells me I get an illegal string offset and the error is the index that's specified. So then I parse the URL, and then do parse_str($query, $output) which in turn allows me to do $output['d'] and THEN I can set a new value to that variable. If I echo it out, it's fine.
But then I get to the http_build_query line, and it tells me that it's expecting an array or object and I can't build the new URL. Here is my code:
$link = parse_url('https://www.google.com/search?source=hp&ei=85GhW6CNHoSqsgXnzoD4Ag&q=coding+tutorial&btnK=Google+Search&oq=coding+tutorial', PHP_URL_QUERY);
parse_str($link, $output);
$output['oq'] = 'new value';
$query_result = http_build_query($link);
echo $query_result;
This code yields that the http_build_query function wants an array or object...i guess i'm not giving it that in some way? What do I need to do to get this to work?
If you want to rebuild the full URL after modifying the query parameters, you could do this:
$url = 'https://www.google.com/search?source=hp&ei=85GhW6CNHoSqsgXnzoD4Ag&q=coding+tutorial&btnK=Google+Search&oq=coding+tutorial';
$link = parse_url($url, PHP_URL_QUERY);
parse_str($link, $output);
$output['oq'] = 'new value';
echo substr($url, 0, strpos($url, '?') + 1) . http_build_query($output);
Output:
https://www.google.com/search?source=hp&ei=85GhW6CNHoSqsgXnzoD4Ag&q=coding+tutorial&btnK=Google+Search&oq=new+value

Hiding part of the url in Zend Framework

I was thinking if there is a way to hide part of the url in PHP/ Zend Framework 2. Something like this:
sitename.com/something/?inviter=1234&id=1
But I'd like to hide the part with the &id=1 somehow, so that when the url is copied and entered by the user, it would look like this:
sitename.com/something/?inviter=1234
And on the other side I can do something like this:
$id = $_GET["id"])
Is this possible to do, if so, how? Maybe there is something close to what I'm looking for to achieve?
You can hide it only with Cookie or Session techniques. But it will work only for one user during one session.
You can parse and rebuild the url using parse_url, http_build_url, with parse_str, and http_build_str.
For example:
/**
* Transform a url using a whitelist of query-string keys
*/
function transformUrlKeepQueryKeys($url, array $whitelist)
{
// Break the given url into parts
$parts = parse_url($url);
// Break the parts into key-value pairs
$query = $parts['query'];
parse_str($query, $queryParts);
// Unset all unwanted keys
foreach (array_keys($queryParts) as $k) {
if (!in_array($k, $whitelist)) {
unset($queryParts[$k]);
}
}
// rebuild the url
$parts['query'] = http_build_query($queryParts);
// return
return http_build_url('', $parts);
}
Invocation should be:
$url = 'http://sitename.com/something/?inviter=1234&id=1';
$whitelist = [
'inviter'
];
$expectedUrl = 'http://sitename.com/something/?inviter=1234';
$actualUrl = transformUrlKeepQueryKeys($url, $whitelist);
assert($expectedUrl == $actualUrl);
Alternatively, you could implement something similar using a blacklist of keys to remove.
The only problem with this is that the function http_build_url is not included in core PHP, but is part of the PECL HTTP extension. If you are unable to install that extension in your environment, then you can use a pure PHP implementation of that function, for example here.

parse non encoded url

there is an external page, that passes a URL using a param value, in the querystring. to my page.
eg: page.php?URL=http://www.domain2.com?foo=bar
i tried saving the param using
$url = $_GET['url']
the problem is the reffering page does not send it encoded. and therefore it recognizes anything trailing the "&" as the beginning of a new param.
i need a way to parse the url in a way that anything trailing the second "?" is part or the passed url and not the acctual querystring.
Get the full querystring and then take out the 'URL=' part of it
$name = http_build_query($_GET);
$name = substr($name, strlen('URL='));
Antonio's answer is probably best. A less elegant way would also work:
$url = $_GET['url'];
$keys = array_keys($_GET);
$i=1;
foreach($_GET as $value) {
$url .= '&'.$keys[$i].'='.$value;
$i++;
}
echo $url;
Something like this might help:
// The full request
$request_full = $_SERVER["REQUEST_URI"];
// Position of the first "?" inside $request_full
$pos_question_mark = strpos($request_full, '?');
// Position of the query itself
$pos_query = $pos_question_mark + 1;
// Extract the malformed query from $request_full
$request_query = substr($request_full, $pos_query);
// Look for patterns that might corrupt the query
if (preg_match('/([^=]+[=])([^\&]+)([\&]+.+)?/', $request_query, $matches)) {
// If a match is found...
if (isset($_GET[$matches[1]])) {
// ... get rid of the original match...
unset($_GET[$matches[1]]);
// ... and replace it with a URL encoded version.
$_GET[$matches[1]] = urlencode($matches[2]);
}
}
As you have hinted in your question, the encoding of the URL you get is not as you want it: a & will mark a new argument for the current URL, not the one in the url parameter. If the URL were encoded correctly, the & would have been escaped as %26.
But, OK, given that you know for sure that everything following url= is not escaped and should be part of that parameter's value, you could do this:
$url = preg_replace("/^.*?([?&]url=(.*?))?$/i", "$2", $_SERVER["REQUEST_URI"]);
So if for example the current URL is:
http://www.myhost.com/page.php?a=1&URL=http://www.domain2.com?foo=bar&test=12
Then the returned value is:
http://www.domain2.com?foo=bar&test=12
See it running on eval.in.

Remove specific parameter from URL while preserving other parameters

I want remove a parameter from a URL:
$linkExample1='https://stackoverflow.com/?name=alaa&counter=1';
$linkExample2='https://stackoverflow.com/?counter=4&star=5';
I am trying to get this result:
https://stackoverflow.com/?name=alaa&
https://stackoverflow.com/?&star=5
I am trying to do it using preg_replace, but I've no idea how it can be done.
$link = preg_replace('~(\?|&)counter=[^&]*~','$1',$link);
Relying on regular expressions can screw things up sometimes..
You should use, the parse_url() function which breaks up the entire URL and presents it to you as an associative array.
Once you have that array, you can edit it as you wish and remove parameters.
Once, completed, use the http_build_url() function to rebuild the URL with the changes made.
Check the docs here..
Parse_Url Http_build_query()
EDIT
Whoops, forgot to mention. After you get the parameter string, youll obviously need to separate the parameters as individual ones. For this you can supply the string as input to the parse_str() function.
You can even use explode() with & as the delimeter to get this done.
I would recommend using a combination of parse_url() and http_build_query().
Handle it correctly! !
remove_query('http://example.com/?a=valueWith**&**inside&b=value');
Code:
function remove_query($url, $which_argument=false){
return preg_replace( '/'. ($which_argument ? '(\&|)'.$which_argument.'(\=(.*?)((?=&(?!amp\;))|$)|(.*?)\b)' : '(\?.*)').'/i' , '', $url);
}
A code example how I would grab a requested URL and remove a parameter called "name", then reload the page:
$url = $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; //complete url
$parts = parse_url($url);
parse_str($parts['query'], $query); //grab the query part
unset($query['name']); //remove a parameter from query
$dest_query = http_build_query($query); //rebuild new query
$dest_url=(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http").'://'.$parts['path'].'?'.$dest_query; //add query to host
header("Location: ".$dest_url); //reload page
parse_url() and parse_str() are buggy. Regular expressions can work but have the tendency to break. If you want to correctly deconstruct, make changes, and then reconstruct a URL, you should look at:
http://barebonescms.com/documentation/ultimate_web_scraper_toolkit/
ExtractURL() generates parse_url()-like output but does much more (and does it right). CondenseURL() takes an array from ExtractURL() and constructs a new URL from the information. Both functions are in the 'support/http.php' file.
Years later...
$_GET can be manipulated like any other array in PHP. Simply unset the key and create the http query using the http_build_query function.
// Populate _GET with sample data...
$_GET = array(
'value_a' => "A",
'key_to_remove' => "Don't delete me bro!",
'value_b' => "B"
);
// Should output everything...
// "value_a=A&key_to_remove=Don%27t+delete+me+bro%21&value_b=B"
echo "\n".http_build_query( $_GET );
// Remove the key from _GET...
unset( $_GET[ 'key_to_remove' ] );
// Should output everything else...
// "value_a=A&value_b=B"
echo "\n".http_build_query( $_GET );
This is working for me:
function removeParameterFromUrl($url, $key)
{
$parsed = parse_url($url);
$path = $parsed['path'];
unset($_GET[$key]);
if(!empty(http_build_query($_GET))){
return $path .'?'. http_build_query($_GET);
} else return $path;
}

Categories