I have a string like this stored in mysql table:
?name1=value1&name2=value2&name3=value3
originally this data was only going to be used to send GET data to another script but now i find myself needing it for other things.
is there a predefined function in PHP for turning these pairs into variable or an array? or will I have to do it manually?
The (poorly-named) PHP function parse_str can do this, though you will need to first trim off the initial question mark.
$arr = array();
parse_str($str, $arr);
print_r($arr);
There are some caveats to this function alluded to in the manual page:
If you call it without the second array parameter it will write the values into the current scope as local variables. This can be dangerous if the string contains keys that may change the value of variables already present in your program.
The magic_quotes_gpc setting affects how this function operates, since this is the routine used internally by PHP to decode query strings and urlencoded POST bodies.
If you need a portable solution that is not affected by the magic_quotes_gpc setting then it's reasonably straightforward to write a decoding function manually, using urldecode to handle the value encoding:
function parseQueryString($queryString) {
$result = array();
$pairs = explode("&", $queryString);
foreach ($pairs as $pair) {
$pairArr = split("=", $pair, 2);
$result[urldecode($pairArr[0])] = urldecode($pairArr[1]);
}
return $result;
}
This solution will probably be slightly slower than the built-in parse_args function, but has the benefit of consistent behavior regardless of how PHP is configured. Of course you will again need to first strip off the ? from the beginning, which is not included in either example.
Var_export Might be useful.
$arr=?name1=value1&name2=value2&name3=value3
var_export($arr);
Related
I'm having a trouble getting my array content when using a declared variable as my array indexes shown below.
$indexes = "[0][1][0][1]";
$code = $params["smv_code"].$indexes;
this returns an "Array to string conversion error";
Note that the $indexes is dynamic depends on the "parent_0_1_0_1" params content of the array index.
the . operator just does a string concatenation - it's not going to work for code like that. I don't think PHP has the ability to interpret raw code like that - at least not safely. (You can always use eval, but there are serious security concerns for using something like that - injection, etc.).
I would suggest just traversing the array "manually" through interpreting the indexes yourself. Change the $indexes to "0,1,0,1" and do the following:
$index_array = explode(',',$indexes)
$code = $params["smv_code"];
foreach($index_array as $i) {
$code=$code[$i];
}
$code at the end should be the value you're looking for.
more out of interested...
$_GET['unique'] = blahblahblah=this_is_what_im_interested_in
I know I can get the second element like this:
$words = explode('=', $_GET['unique']);
echo $words[1];
Is there a way to get this in a single line? - that would then 'hopefully' allow me to add that to function/object call:
$common->resetPasswordReply(... in here I would put it....);
like
$common->resetPasswordReply(explode('=', $_GET['unique'])[1]);
I'm just interested to see if this is possible.
PHP supports the indexing on functions if they are returning arrays/objects; so the following would work too:
echo explode('=', $_GET['unique'])[1];
EDIT
This is termed as array dereferencing and has been covered in PHP documentations:
As of PHP 5.4 it is possible to array dereference the result of a
function or method call directly. Before it was only possible using a
temporary variable.
As of PHP 5.5 it is possible to array dereference an array literal.
This should do it for you.
substr($str, strpos($str, "=")+1);
Strangely enough you can 'almost' do this with list(), but you can't use it in a function call. I only post it as you say 'more out of interest' :-
$_GET['unique'] = "blahblahblah=this_is_what_im_interested_in";
list(, $second) = explode('=', $_GET['unique']);
var_dump($second);
Output:-
string 'this_is_what_im_interested_in' (length=29)
You can see good examples of how flexible list() is in the first set of examples on the manual page.
I think it is worth pointing out that although your example will work:-
$common->resetPasswordReply(explode('=', $_GET['unique'])[1]);
it does kind of obfuscate your code and it is not obvious what you are passing into the function. Whereas something like the following is much more readable:-
list(, $replyText) = explode('=', $_GET['unique']);
$common->resetPasswordReply($replyText));
Think about coming back to your code in 6 months time and trying to debug it. Make it as self documenting as possible. Also, don't forget that, as you are taking user input here, it will need to be sanitised at some point.
(NOTE: This is a follow up to a previous question, How to pass an array within a query string?, where I asked about standard methods for passing arrays within query strings.)
I now have some PHP code that needs to consume the said query string- What kind of query string array formats does PHP recognize, and do I have to do anything special to retrieve the array?
The following doesn't seem to work:
Query string:
?formparts=[a,b,c]
PHP:
$myarray = $_GET["formparts"];
echo gettype($myarray)
result:
string
Your query string should rather look like this:
?formparts[]=a&formparts[]=b&formparts[]=c
If you're dealing with a query string, you are looking at the $_GET variable. This will contain everything after the ? in your previous question.
So what you will have to do is pretty much the opposite of the other question.
$products = array();
// ... Add some checking of $_GET to make sure it is sane
....
// then assign..
$products = explode(',', $_GET['pname']);
and so on for each variable. I must give you a full warning here, you MUST check what comes through the $_GET variable to make sure it is sane. Otherwise you risk having your site compromised.
I'm trying to change a variable name in a query string, so it's usable by my PHP code.
The query gets posts from an external system, so I can't control that they are posting a variable name with a space in it. And that makes it impossible for me to use the PHP $_GET function.
I need to change variable%20name to ?new1
And I need to change variable2 to new2
There are many variables passed in the query, but only these two need to be changed. The rest can stay the same or even disappear.
So ?variable%20name=abc&variable2=xyz
Needs to end up as ?new1=abc&new2=xyz
Also, they may not be in this order and there may be more variables
So ?variable%20name=abc&blah=123&blah2=456&variable2=xyz
Could end up as ?new1=abc&new2=xyz
OR as ?new1=abc&blah=123&blah2=456&new2=xyz
Either way would be fine!
Please give me the mod_rewrite rule that will fix this.
Thank you in advance!
Parsing the query string with mod_rewrite is a bit of a pain, has to be done with RewriteCond and using %n replacements in a subsequent RewriteRule, probably easier to manually break up the original query string in PHP.
The full query string can be found (within PHP) in $_SERVER['QUERY_STRING'].
You can split it up using preg_split() or explode(), first on &, then on =, to get key/value pairs.
Using custom%20cbid=123&blahblahblah&name=example as an example.
$params = array();
foreach (explode("&", $_SERVER['QUERY_STRING']) as $cKeyValue) {
list ($cKey, $cValue) = explode('=', $cKeyValue, 2);
$params[urldecode($cKey)] = urldecode($cValue);
}
// Would result in:
$params = array('custom cbid' => 123,
'blahblahblah' => NULL,
'name' => example);
I'm new to OOP and want to revamp this function to get rid of using globals.
function CatchListing() {
$parseform = array('itemnum','msrp','edprice','itemtype','box','box2','box25','box3','box4','box5','box6','box7','itemcolor','link');
foreach ($parseform as $globalName) {
$GLOBALS[$globalName] = mysql_real_escape_string($_POST[$globalName]);
}
}
I was told to use array_map & then extact, but I am not sure of how to structure this.
function CatchListing() {
$_POST['listing'] = array_map('mysql_real_escape_string', $_POST);
$nst = extract($_POST['listing']);
}
(listing is the form name btw)
Thanks
Be VERY careful about using extract with externally inputted values as from $_GET and $_POST.
you're much better off extracting the values manually to known values.
It's far too easy for an extract from _GET or _POST to clobber existing variables.
There are so many things to say and Jonathan makes a very good start. Every time the user has the opportunity to play with your internal data and you don't check them, there is a huge "opportunity" (depends on the view..) that something goes wrong. Here is another approach on how to "maybe" get where you want to go:
<?php
function Sanitize($string){
return mysql_real_escape_string(trim($string));
}
function CatchListing(){
foreach($_POST as $key => $value) {
$key = Sanitize($key);
$value = Sanitize($value);
if($key && $value && !$GLOBALS[$key]){ /* prevent overwriting existing globals*/
$GLOBALS[$key] = $value;
}
}
}
global $nice;
$nice = "working";
CatchListing();
print_r($GLOBALS);
?>
To be honest, it still has not really anything to do with OOP and furthermore should be seen as a procedural approach. Personally I would use an additional and reusable function to "sanitize" the input, because you never know, if someday you want to change your database or the "escape" function and then you exactly know where to look for possible changes. Ah one more thing: Are you certain that you don't know all the possible names of all the variables you have to expect? Maybe you can predetermine them and put them in another array and check each user supplied argument with in_array.
To completely get rid of the usage of globals in your code, and also to make it much better overall, you can do something along these lines:
stop using $_POST, as it's a superglobal. When code needs values from superglobals, pass them as parameters
don't store values into $GLOBALS. If you need to return more than one value, consider returning an object or an array
Here's how I think I would modify your code to improve it:
function CatchListings($listings) {
$filteredListings = array_map('mysql_real_escape_string', $listings);
//I assume you only need the values in the array in the original snippet,
//so we need to grab them from the parameter array and return only that
$requiredListings = array();
$requiredKeys = array('itemnum','msrp','edprice','itemtype','box','box2','box25','box3','box4','box5','box6','box7','itemcolor','link');
foreach($requiredKeys as $key) {
$requiredListings[$key] = $filteredListings[$key];
}
return $requiredListings;
}
To use this function, you simply do $result = CatchListings($_POST);. Same result, no globals used.
There is one thing to consider, though. It may not be best possible form to just pass a randomly filled array (ie. $_POST) to the function, and expect it to contain specific keys (ie. $requiredKeys array). You might want to either add logic to check for missing keys, or process the post array before passing it.