I want to add a query string to a URL, however, the URL format is unpredictable. The URL can be
http://example.com/page/ -> http://example.com/page/?myquery=string
http://example.com/page -> http://example.com/page?myquery=string
http://example.com?p=page -> http://example.com?p=page&myquery=string
These are the URLs I'm thinking of, but it's possible that there are other formats that I'm not aware of.
I'm wondering if there is a standard, library or a common way to do this. I'm using PHP.
Edit: I'm using Cbroe explanation and Passerby code. There is another function by Hamza but I guess it'd be better to use PHP functions and also have cleaner/shorter code.
function addQuery($url,array $query)
{
$cache=parse_url($url,PHP_URL_QUERY);
if(empty($cache)) return $url."?".http_build_query($query);
else return $url."&".http_build_query($query);
}
// test
$test=array("http://example.com/page/","http://example.com/page","http://example.com/?p=page");
print_r(array_map(function($v){
return addQuery($v,array("myquery"=>"string"));
},$test));
Live demo
I'm wondering if there is a standard, library or a common way to do this. I'm using PHP.
Depends on how failsafe – and thereby more complex – you want it to be.
The simplest way would be to look for whether there’s a ? in the URL – if so, append &myquery=string, else append ?myquery=string. This should cover most cases of standards-compliant URLs just fine.
If you want it more complex, you could take the URL apart using parse_url and then parse_str, then add the key myquery with value string to the array the second function returns – and then put it all back together again, using http_build_query for the new query string part.
Some spaghetti Code:
echo addToUrl('http://example.com/page/','myquery', 'string').'<br>';
echo addToUrl('http://example.com/page','myquery', 'string').'<br>';
echo addToUrl('http://example.com/page/wut/?aaa=2','myquery', 'string').'<br>';
echo addToUrl('http://example.com?p=page','myquery', 'string');
function addToUrl($url, $var, $val){
$array = parse_url($url);
if(isset($array['query'])){
parse_str($array['query'], $values);
}
$values[$var] = $val;
unset($array['query']);
$options = '';$c = count($values) - 1;
$i=0;
foreach($values as $k => $v){
if($i == $c){
$options .= $k.'='.$v;
}else{
$options .= $k.'='.$v.'&';
}
$i++;
}
$return = $array['scheme'].'://'.$array['host'].(isset($array['path']) ? $array['path']: '') . '?' . $options;
return $return;
}
Results:
http://example.com/page/?myquery=string
http://example.com/page?myquery=string
http://example.com/page/wut/?aaa=2&myquery=string
http://example.com?p=page&myquery=string
You should try the http_build_query() function, I think that's what you're looking for, and maybe a bit of parse_str(), too.
Related
I'm creating module for an application which will have simple custom templating with tags that will be replaced with data from a database. The field names will be different in each instance of this module. I want to know if there is a better way to do this.
The code below is what I've come up with, But I believe there must be a better way. I struggled with preg_split and preg_match_all and just hit my limit so I did it the dumb person way.
<?php
$customTemplate = "
<div>
<<This>>
<<that>>
</div>
";
function process_template ($template, $begin = '<<', $end = '>>') {
$begin_exploded = explode($begin, $template);
if (is_array($begin_exploded)) {
foreach ($begin_exploded as $key1 => $value1) {
$end_exploded = explode($end, $value1);
if (is_array($end_exploded)) {
foreach ($end_exploded as $key2 => $value2) {
$tag = $begin.$value2.$end;
$variable = trim($value2);
$find_it = strpos($template,$tag);
if ($find_it !== false) {
//str_replace ($tag, $MyClass->get($variable), $template );
$template = str_replace ($tag, $variable, $template);
}
}
}
}
}
return $template;
}
echo(process_template($customTemplate));
/* Will Echo
<div>
This
that
</div>
*/
?>
In the future I will connect $MyClass->get() to replace the tag with the proper data. And the custom template will be built by the user.
Rather than preg_split or preg_match I would rather use preg_replace_callback, since you are doing replacements, and the replacement value is derived from what looks like will end up being a method in another class.
function process_template($template, $begin = '<<', $end = '>>') {
// get $MyClass in the function scope somehow. Maybe pass it as another parameter?
return preg_replace_callback("/$begin(\w+)$end/", function($var) use ($MyClass) {
return $MyClass->get($var[1]);
}, $template);
}
Here's an example to play with: https://3v4l.org/N1p03
I assume this is just for fun/learning. If I really needed to use a template for something I would rather start with composer require "twig/twig:^2.0" instead. In fact, if you're interested in learning more about how it works you could go check out a well-established system like twig or blade does it. (Better than I've done it in this answer.)
There are tons templating engines around, but sometimes... just add complexity and dependencies for a maybe simple thing. This a modified sample of what I used for make some javascript corrections. This works for your template.
function process_template($html,$b='<<',$e='>>'){
$replace=['this'=>'<input name="this" />','that'=>'<input name="that" />'];
if(preg_match_all('/('.$b.')(.*?)('.$e.')/is',$html,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE)){
$t='';$o=0;
foreach($matches as $m){
//for reference $m[1][0] contains $b, $m[2][0] contains $e
$t.=substr($html,$o,$m[0][1]-$o);
$t.=$replace[$m[2][0]];
$o=$m[3][1]+strlen($m[3][0]);
}
$t.=substr($html,$o);
$html=$t;
}
return $html;
}
$html="
<div>
<<this>>
<<that>>
</div>
";
$new=process_template($html);
echo $new;
For demo purpose I put the array $replace that handling the substitutions. You replace those with your function that will handle the replacement.
Here is a working snippet: https://3v4l.org/MBnbR
I like this function because you have control of what to replace and what to put back on the final result. By the way by using the PREG_OFFSET_CAPTURE also return on the matches the position where the regexp groups happens. Those are on the $m[x][1]. The captured text will be on $m[x][0].
I'm currently building a project with Laravel and I need to build URLs with query strings. URL:: functions and url(), action(), etc. are out of the question since they mainly built for internal use. The urls I need to create are external.
A similar example I could give is an external URL for the static images Google Maps api :
https://maps.googleapis.com/maps/api/staticmap?center=New+York,NY&zoom=13&size=600x300&key=KEY
If you have the array :
<!-- language: lang-php -->
array(
'center'=>'New York, NY',
'zoom'=>13,
'size'=>'600x300'
)
I'm mainly asking that because it's currently impossible for me to install http_build_url / query extension and because there are many functions that do this internally. I just can't find the best place to "plug" myself.
If you need to reinvent the wheel (which sucks, sorry to hear), you could do something like this.
$queryString = '';
$arrayLength = count($myArray);
foreach ($myArray as $key => $val) {
$queryString .= urlencode($key) . '=' . urlencode($val);
$arrayLength--;
if ($arrayLength) {
$queryString .= '&';
}
}
I'd save it as a function, and have a separate function for constructing the url, e.g.
function buildUrl($baseUri, $params) {
return sprintf("%s?%s", $baseUri, buildQueryString($params));
}
But I'm not 100 % that this is what you really want, so apologies if I'm wrong.
Edit: Four years later, given that they asked for Laravel methods, I would do something like this:
collect($array)->map(function ($value, $key) {
return urlencode($key) . '=' . urlencode($value);
})->join('&');
Simple string concatenating:
$myStr = 'puppies.';
echo 'Dogs have '.$myStr;
Output:
Dogs have puppies.
You can just concatenate the elements of the array with the url string in the same manner:
$values = Array(
'center'=>'New York, NY',
'zoom'=>13,
'size'=>'600x300'
)
$urlTemp = 'https://maps.googleapis.com/maps/api/staticmapcenter=';
$url = $urlTemp.$values['center']
.'&zoom='.$values['zoom']
.'&size='.$values['size']
.'&key=KEY';
You're searching for this function: http://php.net/manual/en/function.http-build-query.php
Cut some word from php available ?
First access to page for example
www.mysite.com/test.php?ABD_07,_oU_876.00/8999&message=success
From my php code, i will get $curreny_link_redirect = test.php?ABD_07,_oU_876.00/8999&message=success
And i want to get $curreny_link_redirect_new = test.php?ABD_07,_oU_876.00/8999
( Cut &message=success )
How can i do ?
<?PHP
$current_link = "$_SERVER[REQUEST_URI]";
$curreny_link_redirect = substr($current_link,1);
$curreny_link_redirect_new = str_replace('', '&message=success', $curreny_link_redirect);
echo $curreny_link_redirect_new;
?>
Your str_replace call is inverse of what it should be. What you want to replace should be the first parameter, not the second.
//Wrong
$curreny_link_redirect_new = str_replace('', '&message=success', $curreny_link_redirect);
//Right
$curreny_link_redirect_new = str_replace('&message=success','', $curreny_link_redirect);
While simple way to do this is to use regex (or even static with str_replace()), I recommend to use built-in functions for url handling. This may be useful when working with complex parameters or multiple parameters:
$data = 'www.mysite.com/test.php?ABD_07,_oU_876.00/8999&message=success';
$url = parse_url($data);
parse_str($url['query'], $url['query']);
//now, do something with parameters:
unset($url['query']['message']);
$url['query'] = http_build_query($url['query']);
$url = http_build_url($url);
-please, note, that http_build_url() is a PECL function (pecl_http to be precise). The way above may look more complex, but it has benefits - first, as I've already mentioned, this will be easy to modify for working with complex parameters or multiple parameters. Second, it will produce valid url - i.e. encode such things as slashes, spaces, e t.c. - in result. Thus, result will always be correct url.
Do like this
<?php
$str = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
echo $str = array_shift(explode('&',$str));
Try this:
$current_link_path = substr($_SERVER['PHP_SELF'], 1);
$params = $_GET;
if ($params['message'] == 'success') {
unset($params['message']);
}
$current_link_redirect = $current_link_path . '?' . http_build_query($params);
Maybe not an answer, but a disclaimer for future visitors:
1) I would strongly recommend the function: http://pl1.php.net/parse_url.
And in that case:
$current_link = "$_SERVER[REQUEST_URI]";
$arguments = explode('&', parse_url($current_link, PHP_URL_QUERY));
print_r($arguments);
2) To build new url, use http://pl1.php.net/manual/en/function.http-build-url.php. This is the best, future modifications ready solution I think.
In that case this solution is a little overkill, but these functions are really great, and worth to introduce here.
Best regards
I'm trying to make links to include the current _GET variables.
Example link: Page 2
The current url is: http://example.com/test.php?id=2&a=1
So if someone clicks on the link of page 2 it will take them to:
http://example.com/test.php?id=2&a=1&page=2
Currently if they click on the link it takes them to:
http://example.com/test.php?page=2
As you can see, I need a way to get the current _GET variables in the url and add them to the link. Advice?
The superglobal entry $_SERVER['QUERY_STRING'] has the query string in it. You could just append that to any further links.
update: The alternate response on this page using http_build_query is better because it lets you add new variables to the query string without worrying about extraneous ?s and such. But I'll leave this here because I wanted to mention that you can access the literal query string that's in the current address.
$new_query_string = http_build_query(array_merge($_GET,array('page' => 2)));
Make use of #extract($_GET). So you can access them directly as variables.
Try this may help you......
function get_all_get()
{
$output = "?";
$firstRun = true;
foreach($_GET as $key=>$val) {
if($key != $parameter) {
if(!$firstRun) {
$output .= "&";
} else {
$firstRun = false;
}
$output .= $key."=".$val;
}
}
return $output;
}
As for the question above how to include the name of php file as well in the url, using Your Common Sense's perfect method and adding a question mark worked for me:
echo "<a href='?".$url."'>link</a>"
Let's say I have some code like this
if(isset($_GET['foo']))
//do something
if(isset($_GET['bar']))
//do something else
If a user is at example.com/?foo=abc and clicks on a link to set bar=xyz, I want to easily take them to example.com/?foo=abc&bar=xyz, rather than example.com/?bar=xyz.
I can think of a few very messy ways to do this, but I'm sure there's something cleaner that I don't know about and haven't been able to track down via Google.
Here's one way....
//get passed params
//(you might do some sanitizing at this point)
$params=$_GET;
//morph the params with new values
$params['bar']='xyz';
//build new query string
$query='';
$sep='?';
foreach($params as $name=>$value)
{
$query.=$sep.$name.'='.urlencode($value);
$sep='&';
}
If you are updating the query string you need ot make sure you don't do something like
$qs="a=1&b=2";
$href="$qs&b=4";
$href contains "a=1&b=2&b=4"
What you really want to do is overwrite the current key if you need to .
You can use a function like this. (disclaimer: Off the top of my head, maybe slightly bugged)
function getUpdateQS($key,$value)
{
foreach ($_GET as $k => $v)
{
if ($k != $key)
{
$qs .= "$k=".urlencode($v)."&"
}
else
{
$qs .= "$key=".urlencode($value)."&";
}
}
return $qs
}
View report
Just set the link that changes bar to xyz to also have foo=abc if foo is already set.
$link = ($_GET['foo'] == 'abc') ? 'foo=abc&bar=xyz' : 'bar=xyz';
?>
Click Me
You would have to render out the links with the proper URL querystring to make that happen. This is a design decision that you would need to make on your end depending on how your system is setup.
I have some sites that have this issue, and what I do is setup a querystring global variable that sets the current page data the top of the page request.
Then when I am rendering the page, if I need to make use of the current query string I do something like:
echo '<a href="myurl.php' . querystring . '&bar=foo';
It's not the cleanest, but it all depends on how your system works.
Save some code and use the built-in http_build_query. I use this wrapper in one of my projects:
function to_query_string($array) {
if(is_scalar($array)) $query = trim($array, '? \t\n\r\0\x0B'); // I could split on "&" and "=" do some urlencode-ing here
else $query = http_build_query($array);
return '?'.$query;
}
Also, though it isn't often used, you can have $_GET on the left-hand side of an assignment:
$_GET['overriden_or_new'] = 'new_value';
echo 'Yeah!';
Other than that, just do what Paul Dixon said.