I am storing an array in string form in a database for later retrieval:
The value of the array happens to be parameters for a filter_val call.
$str = 'array("options" => array("min_range" => 4))';
I know I can use
eval('$options = ' . $str . ';');
to prepare this value for passing to filter_val, but is there any other way to do this?
This related post (while excellent) didn't handle my exact issue.
I would not use eval() to get your string functional. For example, the function eval may be disallowed on some hosts, thus your application will not work.
A more appropriate way would be to store your options in a json_encode()'d string, and decode when you need.
$options = json_decode($options_from_db);
Or as John Conde mentions, you can serialise it.
Related
I see many questions about passing an array as a query string in PHP, and it seems the prevailing way is using brackets as in key[]=foo&key[]=bar.
However I cannot find a straight answer about how to send an object (or a key=>value associative array - same thing) as a query string.
Currently, however I do it is:
STRING
?foo=bar&hello=world
Then on the server side, I would do:
<?php
$array = array();
$array['foo']=$_GET['foo'];
$array['hello']=$_GET['hello'];
?>
Of course when using $_POST, this is very simple with an ajax request. Any object you send automatically serializes and isn't a problem.
Is this the best way to handle it, or is there some other standard for sending an object in a query string using PHP?
You can use an associative array in a form and in the query string:
object[foo]=bar&object[hello]=world
To build it URL encoded:
$data['object']['foo'] = 'bar';
$data['object']['hello'] = 'world';
echo http_build_query($data);
Yields:
object%5Bfoo%5D=bar&object%5Bhello%5D=world
You can go many levels and/or use dynamically added elements. In general, in text form, it looks just like a PHP array
object[foo][more][even more][]
Or:
object[foo][][more][even more]
I'm working with Zend Framework 2's session manager in PHP, and want to unserialize the session data so I can change the way the data is stored. I thought regex was the way to do it, but I can't figure out how to make sure the regex is right for this type of string.
Sample input:
__ZF|a:2:{s:20:"_REQUEST_ACCESS_TIME";d:1099999999.9999999999999999999999;s:6:"_VALID";a:1:{s:25:"Zend\Session\Validator\Id";s:26:"xxxxxxxxxxxxxxxxxxxxxxxxxx";}}initialized|C:23:"Zend\Stdlib\ArrayObject":403:{a:4:{s:7:"storage";a:3:{s:4:"init";i:1;s:10:"remoteAddr";s:13:"127.000.00.01";s:13:"httpUserAgent";s:114:"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";}s:4:"flag";i:2;s:13:"iteratorClass";s:13:"ArrayIterator";s:19:"protectedProperties";a:4:{i:0;s:7:"storage";i:1;s:4:"flag";i:2;s:13:"iteratorClass";i:3;s:19:"protectedProperties";}}}
Expected output:
'__ZF|a:2:{s:20:"_REQUEST_ACCESS_TIME";d:1099999999.9999999999999999999999;s:6:"_VALID";a:1:{s:25:"Zend\Session\Validator\Id";s:26:"xxxxxxxxxxxxxxxxxxxxxxxxxx";}}'
'initialized|C:23:"Zend\Stdlib\ArrayObject":403:{a:4:{s:7:"storage";a:3:{s:4:"init";i:1;s:10:"remoteAddr";s:13:"127.000.00.01";s:13:"httpUserAgent";s:114:"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";}s:4:"flag";i:2;s:13:"iteratorClass";s:13:"ArrayIterator";s:19:"protectedProperties";a:4:{i:0;s:7:"storage";i:1;s:4:"flag";i:2;s:13:"iteratorClass";i:3;s:19:"protectedProperties";}}}'
What I tried:
$pattern = '/\w+\|.*?}}+/'; // this works for the sample input, but may be too general and certainly won't work for serialized data without a nested array
$pattern = '/\w+\|(a:\d+:{.*?}|o:\d+:\"[a-z0-9_]+\":\d+:{.*?})/'; // doesn't capture the `initialized` data
Where I am stuck:
Put generally, I can't figure out the best way to split apart the __ZF data from the initialized data (especially when there are other non-Zend variables in the session). Specifically, I can't figure out what regex to use to get serialized data.
I tried to put an example on RegexPlanet, but couldn't figure out the interface, and it only seemed to produce bizarre results. If it helps, I'm fairly sure ZF PHP produces its serialized session data like this:
$text = "";
foreach ($_SESSION as $key => $value) {
$text .= $key . "|" . serialize($value);
}
...but I haven't found the source code for that.
I found out about ini_set('session.serialize_handler', 'php_serialize'); It changes the serialization to use PHP's regular serialize method instead of the alternate, which solves the problem. – Miryafa
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);
I want to create an url out of an array with the help of http_build_query (PHP). This is the Array:
$a = array("skip" => 1, "limit" => 1, "startkey" => '["naturalProduct","Apple"]')
After calling
$s = http_build_query($a);
I get the following string $s:
skip=1&limit=1&startkey=%5B%22naturalProduct%22%2C%22Apple%22%5D
My problem is, that I would need an url like this:
skip=1&limit=1&startkey=["naturalProduct","Apple"]
which means, that I don't want to convert the following symbols: ",[]
I have written a conversion function which I call after the http_build_query:
str_replace(array("%5B", "%22", "%5D", "%2C"), array('[', '"', ']', ','), $uri);
My question now: Is there a better way to reach the expected results?
My question now: Is there a better way to reach the expected results?
Yes, there is something better. http_build_queryDocs by default uses an URL encoding as outlined in RFC 1738. You just want to de-urlencode the string. For that there is a function that does this in your case: urldecodeDocs:
$s = http_build_query($a);
echo urldecode($s);
I hope you are aware that your URL then is no longer a valid URL after you've done that. You already decoded it.
You don't need to decode the special characters - they are automatically decoded when PHP's $_GET superglobal is generated. When I do print_r($_GET) with your generated string, I get this:
Array ( [skip] => 1 [limit] => 1 [startkey] => [\"naturalProduct\",\"Apple\"] )
Which has decoded every character, but hasn't unescaped the double quotes. To unescape them, use stripslashes():
echo stripslashes($_GET['startkey']);
This gives
["naturalProduct","Apple"]
Which you can then parse or use however you wish. A better solution, as ThiefMaster mentions in the comments, is to disabled magic_quotes_gpc in your php.ini; it's deprecated and scheduled for removal completely in PHP6.
What would you say is the most efficient way to get a single value out of an Array. I know what it is, I know where it is. Currently I'm doing it with:
$array = unserialize($storedArray);
$var = $array['keyOne'];
Wondering if there is a better way.
You are doing it fine, I can't think of a better way than what you are doing.
You unserialize
You get an array
You get value by specifying index
That's the way it can be done.
Wondering if there is a better way.
For the example you give with the array, I think you're fine.
If the serialized string contains data and objects you don't want to unserialize (e.g. creating objects you really don't want to have), you can use the Serialized PHP library which is a complete parser for serialized data.
It offers low-level access to serialized data statically, so you can only extract a subset of data and/or manipulate the serialized data w/o unserializing it. However that looks too much for your example as you only have an array and you don't need to filter/differ too much I guess.
Its most efficient way you can do, unserialize and get data, if you need optimize dont store all variables serialized.
Also there is always way to parse it with regexp :)
If you dont want to unseralize the whole thing (which can be costly, especially for more complex objects), you can just do a strpos and look for the features you want and extract them
Sure.
If you need a better way - DO NOT USE serialized arrays.
Serialization is just a transport format, of VERY limited use.
If you need some optimized variant - there are hundreds of them.
For example, you can pass some single scalar variable instead of whole array. And access it immediately
I, too, think the right way is to un-serialize.
But another way could be to use string operations, when you know what you want from the array:
$storedArray = 'a:2:{s:4:"test";s:2:"ja";s:6:"keyOne";i:5;}';
# another: a:2:{s:4:"test";s:2:"ja";s:6:"keyOne";s:3:"sdf";}
$split = explode('keyOne', $storedArray, 2);
# $split[1] contains the value and junk before and after the value
$splitagain = explode(';', $split[1], 3);
# $splitagain[1] should be the value with type information
$value = array_pop(explode(':', $splitagain[1], 3));
# $value contains the value
Now, someone up for a benchmark? ;)
Another way might be RegEx ?