Invalid JSON parsing using PHP - php

I'm pulling a JSON feed that is invalid JSON. It's missing quotes entirely. I've tried a few things, like explode() and str_replace(), to get the string looking a little bit more like valid JSON, but with an associate JSON string inside, it generally gets screwed up.
Here's an example:
id:43015,name:'John Doe',level:15,systems:[{t:6,glr:1242,n:'server',s:185,c:9}],classs:0,subclass:5
Are there any JSON parsers for php out there that can handle invalid JSON like this?
Edit: I'm trying to use json_decode() on this string. It returns nothing.

All the quotes should be double quotes " and not single quotes '.
All the keys should be quoted.
The whole element should be an object.
function my_json_decode($s) {
$s = str_replace(
array('"', "'"),
array('\"', '"'),
$s
);
$s = preg_replace('/(\w+):/i', '"\1":', $s);
return json_decode(sprintf('{%s}', $s));
}

This regex will do the trick
$json = preg_replace('/([{,])(\s*)([A-Za-z0-9_\-]+?)\s*:/','$1"$3":',$json);

From my experience Marko's answer doesnt work anymore. For newer php versions use this istead:
$a = "{id:43015,name:'John Doe',level:15,systems:[{t:6,glr:1242,n:'server',s:185,c:988}],classs:0,subclass:5}";
$a = preg_replace('/(,|\{)[ \t\n]*(\w+)[ ]*:[ ]*/','$1"$2":',$a);
$a = preg_replace('/":\'?([^\[\]\{\}]*?)\'?[ \n\t]*(,"|\}$|\]$|\}\]|\]\}|\}|\])/','":"$1"$2',$a);
print_r($a);

I know this question is old, but I hope this helps someone.
I had a similar problem, in that I wanted to accept JSON as a user input, but didn't want to require tedious "quotes" around every key. Furthermore, I didn't want to require quotes around the values either, but still parse valid numbers.
The simplest way seemed to be writing a custom parser.
I came up with this, which parses to nested associative / indexed arrays:
function loose_json_decode($json) {
$rgxjson = '%((?:\{[^\{\}\[\]]*\})|(?:\[[^\{\}\[\]]*\]))%';
$rgxstr = '%("(?:[^"\\\\]*|\\\\\\\\|\\\\"|\\\\)*"|\'(?:[^\'\\\\]*|\\\\\\\\|\\\\\'|\\\\)*\')%';
$rgxnum = '%^\s*([+-]?(\d+(\.\d*)?|\d*\.\d+)(e[+-]?\d+)?|0x[0-9a-f]+)\s*$%i';
$rgxchr1 = '%^'.chr(1).'\\d+'.chr(1).'$%';
$rgxchr2 = '%^'.chr(2).'\\d+'.chr(2).'$%';
$chrs = array(chr(2),chr(1));
$escs = array(chr(2).chr(2),chr(2).chr(1));
$nodes = array();
$strings = array();
# escape use of chr(1)
$json = str_replace($chrs,$escs,$json);
# parse out existing strings
$pieces = preg_split($rgxstr,$json,-1,PREG_SPLIT_DELIM_CAPTURE);
for($i=1;$i<count($pieces);$i+=2) {
$strings []= str_replace($escs,$chrs,str_replace(array('\\\\','\\\'','\\"'),array('\\','\'','"'),substr($pieces[$i],1,-1)));
$pieces[$i] = chr(2) . (count($strings)-1) . chr(2);
}
$json = implode($pieces);
# parse json
while(1) {
$pieces = preg_split($rgxjson,$json,-1,PREG_SPLIT_DELIM_CAPTURE);
for($i=1;$i<count($pieces);$i+=2) {
$nodes []= $pieces[$i];
$pieces[$i] = chr(1) . (count($nodes)-1) . chr(1);
}
$json = implode($pieces);
if(!preg_match($rgxjson,$json)) break;
}
# build associative array
for($i=0,$l=count($nodes);$i<$l;$i++) {
$obj = explode(',',substr($nodes[$i],1,-1));
$arr = $nodes[$i][0] == '[';
if($arr) {
for($j=0;$j<count($obj);$j++) {
if(preg_match($rgxchr1,$obj[$j])) $obj[$j] = $nodes[+substr($obj[$j],1,-1)];
else if(preg_match($rgxchr2,$obj[$j])) $obj[$j] = $strings[+substr($obj[$j],1,-1)];
else if(preg_match($rgxnum,$obj[$j])) $obj[$j] = +trim($obj[$j]);
else $obj[$j] = trim(str_replace($escs,$chrs,$obj[$j]));
}
$nodes[$i] = $obj;
} else {
$data = array();
for($j=0;$j<count($obj);$j++) {
$kv = explode(':',$obj[$j],2);
if(preg_match($rgxchr1,$kv[0])) $kv[0] = $nodes[+substr($kv[0],1,-1)];
else if(preg_match($rgxchr2,$kv[0])) $kv[0] = $strings[+substr($kv[0],1,-1)];
else if(preg_match($rgxnum,$kv[0])) $kv[0] = +trim($kv[0]);
else $kv[0] = trim(str_replace($escs,$chrs,$kv[0]));
if(preg_match($rgxchr1,$kv[1])) $kv[1] = $nodes[+substr($kv[1],1,-1)];
else if(preg_match($rgxchr2,$kv[1])) $kv[1] = $strings[+substr($kv[1],1,-1)];
else if(preg_match($rgxnum,$kv[1])) $kv[1] = +trim($kv[1]);
else $kv[1] = trim(str_replace($escs,$chrs,$kv[1]));
$data[$kv[0]] = $kv[1];
}
$nodes[$i] = $data;
}
}
return $nodes[count($nodes)-1];
}
Note that it does not catch errors or bad formatting...
For your situation, it looks like you'd want to add {}'s around it (as json_decode also requires):
$data = loose_json_decode('{' . $json . '}');
which for me yields:
array(6) {
["id"]=>
int(43015)
["name"]=>
string(8) "John Doe"
["level"]=>
int(15)
["systems"]=>
array(1) {
[0]=>
array(5) {
["t"]=>
int(6)
["glr"]=>
int(1242)
["n"]=>
string(6) "server"
["s"]=>
int(185)
["c"]=>
int(9)
}
}
["classs"]=>
int(0)
["subclass"]=>
int(5)
}

$json = preg_replace('/([{,])(\s*)([A-Za-z0-9_\-]+?)\s*:/','$1"$3":',$json);// adding->(")
$json = str_replace("'",'"', $json);// replacing->(')
This solution seems to be enough for most common purposes.

I'd say your best bet is to download the source of a JSON decoder (they're not huge) and fiddle with it, especially if you know what's wrong with the JSON you're trying to decode.
The example you provided needs { } around it, too, which may help.

This is my solution to remove trailing/leading/multi commas. It can be combined with other answers that remove single quotes and add quotes around json keys. I realize this would not be relevant to the OP as it deals with other types of invalid json however I just hope to help someone who finds this question on a google search.
function replace_unquoted_text ($json, $f)
{
$matches = array();
preg_match_all('/(")(?:(?=(\\\\?))\2.)*?\1/', $json, $matches, PREG_OFFSET_CAPTURE);
//echo '<pre>' . json_encode($matches[0]) . '</pre>';
$matchIndexes = [0];
foreach ($matches[0] as $match)
{
array_push($matchIndexes, $match[1]);
array_push($matchIndexes, strlen($match[0]) + $match[1]);
}
array_push($matchIndexes, strlen($json));
$components = [];
for ($n = 0; $n < count($matchIndexes); $n += 2)
{
$startIDX = $matchIndexes[$n];
$finalExclIDX = $matchIndexes[$n + 1];
//echo $startIDX . ' -> ' . $finalExclIDX . '<br>';
$len = $finalExclIDX - $startIDX;
if ($len === 0) continue;
$prevIDX = ($n === 0) ? 0 : $matchIndexes[$n - 1];
array_push($components, substr($json, $prevIDX, $startIDX - $prevIDX));
array_push($components, $f(substr($json, $startIDX, $len)));
array_push($components, substr($json, $finalExclIDX, ((($n + 1) === count($matchIndexes)) ? count($json) : $matchIndexes[$n + 1]) - $finalExclIDX));
}
//echo '<pre>' . json_encode($components) . '</pre>';
return implode("", $components);
}
function json_decode_lazy ($jsonSnip) {
return json_decode(fix_lazy_json($jsonSnip));
}
function fix_lazy_json ($json) {
return replace_unquoted_text($json, 'fix_lazy_snip');
}
function fix_lazy_snip ($jsonSnip) {
return remove_multi_commas_snip(remove_leading_commas_snip(remove_trailing_commas_snip($jsonSnip)));
}
function remove_leading_commas ($json) {
return replace_unquoted_text($json, 'remove_leading_commas_snip');
}
function remove_leading_commas_snip ($jsonSnip) {
return preg_replace('/([{[]\s*)(,\s*)*/', '$1', $jsonSnip);
}
function remove_trailing_commas ($json) {
return replace_unquoted_text($json, 'remove_trailing_commas_snip');
}
function remove_trailing_commas_snip ($jsonSnip) {
return preg_replace('/(,\s*)*,(\s*[}\]])/', '$2', $jsonSnip);
}
function remove_multi_commas ($json) {
return replace_unquoted_text($json, 'remove_multi_commas_snip');
}
function remove_multi_commas_snip ($jsonSnip) {
return preg_replace('/(,\s*)+,/', ',', $jsonSnip);
}
json_decode_lazy('[,,{,,,"a":17,,, "b":13,,,,},,,]') // {"a":17, "b":13}
See on repl.it.

Related

PHP Properties Parser

Im making a property parser, and I want it to be able to parse a string of any length.
For example, I would like to be able to do the following call:
getDynamicProp("cheese:no;sauce:yes;chicken:brown", "sauce");
and have "yes" returned from it.
Here is what I've got so far:
function getDynamicProp($string , $property){
$args = func_num_args();
$args_val = func_get_args();
$strlen = mb_strlen($string);
$propstrstart = mb_strpos($string , $property . ":");
$propstrend1 = substr($string , $propstrstart , )
$propstrend = mb_strpos($string , ";" , $propstrstart);
$finalvalue = substr($string , $propstrstart , $propstrend);
$val = str_replace($property . ":" , "" , $finalvalue);
$val2 = str_replace(";" , "" , $val);
return $val2;
}
You can try this. The function uses explode to transform strings into arrays, which are more easily manipulable :
function getDynamicProp($string , $property){
$the_result = array();
$the_array = explode(";", $string);
foreach ($the_array as $prop) {
$the_prop = explode(":", $prop);
$the_result[$the_prop[0]] = $the_prop[1];
}
return $the_result[$property];
}
$the_string = "cheese:no;sauce:yes;chicken:brown";
echo getDynamicProp($the_string,"cheese");
echo getDynamicProp($the_string,"sauce");
echo getDynamicProp($the_string,"chicken");
I think you make it over-complicated, or I didn't understand what you want.
I will go with regex instead of making position search.
Here is what I'll use:
function getDynamicProp($string , $property){
if (preg_match('/(^|;)' . $property . ':(?P<value>[^;]+)/', $string, $matches)) {
return $matches['value'];
}
return false;
}
Check here to visualize regex
You would be better off using json_encode and json_decode if you are in control of this string. If not it's much easier like this:
function getDynamicProp($string, $property) {
$string = str_replace(array(':',';'), array('=','&'), $string);
parse_str($string, $result);
return $result[$property];
}
Or store them as cheese=no&sauce=yes&chicken=brown. Then it's even easier still.

Parse string containing dots in php

I would parse the following string:
$str = 'ProceduresCustomer.tipi_id=10&ProceduresCustomer.id=1';
parse_str($str,$f);
I wish that $f be parsed into:
array(
'ProceduresCustomer.tipi_id' => '10',
'ProceduresCustomer.id' => '1'
)
Actually, the parse_str returns
array(
'ProceduresCustomer_tipi_id' => '10',
'ProceduresCustomer_id' => '1'
)
Beside writing my own function, does anybody know if there is a php function for that?
From the PHP Manual:
Dots and spaces in variable names are converted to underscores. For example <input name="a.b" /> becomes $_REQUEST["a_b"].
So, it is not possible. parse_str() will convert all periods to underscores. If you really can't avoid using periods in your query variable names, you will have to write custom function to achieve this.
The following function (taken from this answer) converts the names of each key-value pair in the query string to their corresponding hexadecimal form and then does a parse_str() on it. Then, they're reverted back to their original form. This way, the periods aren't touched:
function parse_qs($data)
{
$data = preg_replace_callback('/(?:^|(?<=&))[^=[]+/', function($match) {
return bin2hex(urldecode($match[0]));
}, $data);
parse_str($data, $values);
return array_combine(array_map('hex2bin', array_keys($values)), $values);
}
Example usage:
$data = parse_qs($_SERVER['QUERY_STRING']);
Quick 'n' dirty.
$str = "ProceduresCustomer.tipi_id=10&ProceduresCustomer.id=1";
function my_func($str){
$expl = explode("&", $str);
foreach($expl as $r){
$tmp = explode("=", $r);
$out[$tmp[0]] = $tmp[1];
}
return $out;
}
var_dump(my_func($str));
array(2) {
["ProceduresCustomer.tipi_id"]=> string(2) "10"
["ProceduresCustomer.id"]=>string(1) "1"
}
This quick-made function attempts to properly parse the query string and returns an array.
The second (optional) parameter $break_dots tells the parser to create a sub-array when encountering a dot (this goes beyond the question, but I included it anyway).
/**
* parse_name -- Parses a string and returns an array of the key path
* if the string is malformed, only return the original string as a key
*
* $str The string to parse
* $break_dot Whether or not to break on dots (default: false)
*
* Examples :
* + parse_name("var[hello][world]") = array("var", "hello", "world")
* + parse_name("var[hello[world]]") = array("var[hello[world]]") // Malformed
* + parse_name("var.hello.world", true) = array("var", "hello", "world")
* + parse_name("var.hello.world") = array("var.hello.world")
* + parse_name("var[hello][world") = array("var[hello][world") // Malformed
*/
function parse_name ($str, $break_dot = false) {
// Output array
$out = array();
// Name buffer
$buf = '';
// Array counter
$acount = 0;
// Whether or not was a closing bracket, in order to avoid empty indexes
$lastbroke = false;
// Loop on chars
foreach (str_split($str) as $c) {
switch ($c) {
// Encountering '[' flushes the buffer to $out and increments the
// array counter
case '[':
if ($acount == 0) {
if (!$lastbroke) $out[] = $buf;
$buf = "";
$acount++;
$lastbroke = false;
// In this case, the name is malformed. Return it as-is
} else return array($str);
break;
// Encountering ']' flushes rge buffer to $out and decrements the
// array counter
case ']':
if ($acount == 1) {
if (!$lastbroke) $out[] = $buf;
$buf = '';
$acount--;
$lastbroke = true;
// In this case, the name is malformed. Return it as-is
} else return array($str);
break;
// If $break_dot is set to true, flush the buffer to $out.
// Otherwise, treat it as a normal char.
case '.':
if ($break_dot) {
if (!$lastbroke) $out[] = $buf;
$buf = '';
$lastbroke = false;
break;
}
// Add every other char to the buffer
default:
$buf .= $c;
$lastbroke = false;
}
}
// If the counter isn't back to 0 then the string is malformed. Return it as-is
if ($acount > 0) return array($str);
// Otherwise, flush the buffer to $out and return it.
if (!$lastbroke) $out[] = $buf;
return $out;
}
/**
* decode_qstr -- Take a query string and decode it to an array
*
* $str The query string
* $break_dot Whether or not to break field names on dots (default: false)
*/
function decode_qstr ($str, $break_dots = false) {
$out = array();
// '&' is the field separator
$a = explode('&', $str);
// For each field=value pair:
foreach ($a as $param) {
// Break on the first equal sign.
$param = explode('=', $param, 2);
// Parse the field name
$key = parse_name($param[0], $break_dots);
// This piece of code creates the array structure according to th
// decomposition given by parse_name()
$array = &$out; // Reference to the last object. Starts to $out
$append = false; // If an empty key is given, treat it like $array[] = 'value'
foreach ($key as $k) {
// If the current ref isn't an array, make it one
if (!is_array($array)) $array = array();
// If the current key is empty, break the loop and append to current ref
if (empty($k)) {
$append = true;
break;
}
// If the key isn't set, set it :)
if (!isset($array[$k])) $array[$k] = NULL;
// In order to walk down the array, we need to first save the ref in
// $array to $tmp
$tmp = &$array;
// Deletes the ref from $array
unset($array);
// Create a new ref to the next item
$array =& $tmp[$k];
// Delete the save
unset($tmp);
}
// If instructed to append, do that
if ($append) $array[] = $param[1];
// Otherwise, just set the value
else $array = $param[1];
// Destroy the ref for good
unset($array);
}
// Return the result
return $out;
}
I tried to correctly handle multi-level keys. The code is a bit hacky, but it should work. I tried to comment the code, comment if you have any question.
Test case:
var_dump(decode_qstr("ProceduresCustomer.tipi_id=10&ProceduresCustomer.id=1"));
// array(2) {
// ["ProceduresCustomer.tipi_id"]=>
// string(2) "10"
// ["ProceduresCustomer.id"]=>
// string(1) "1"
// }
var_dump(decode_qstr("ProceduresCustomer.tipi_id=10&ProceduresCustomer.id=1", true));
// array(1) {
// ["ProceduresCustomer"]=>
// array(2) {
// ["tipi_id"]=>
// string(2) "10"
// ["id"]=>
// string(1) "1"
// }
// }
I would like to add my solution as well, because I had trouble finding one that did all I needed and would handle all circumstances. I tested it quite thoroughly. It keeps dots and spaces and unmatched square brackets (normally changed to underscores), plus it handles arrays in the input well. Tested in PHP 8.0.0 and 8.0.14.
const periodPlaceholder = 'QQleQPunT';
const spacePlaceholder = 'QQleQSpaTIE';
function parse_str_clean($querystr): array {
// without the converting of spaces and dots etc to underscores.
$qquerystr = str_ireplace(['.','%2E','+',' ','%20'], [periodPlaceholder,periodPlaceholder,spacePlaceholder,spacePlaceholder,spacePlaceholder], $querystr);
$arr = null ; parse_str($qquerystr, $arr);
sanitizeArr($arr, $querystr);
return $arr;
}
function sanitizeArr(&$arr, $querystr) {
foreach($arr as $key=>$val) {
// restore values to original
if ( is_string($val)) {
$newval = str_replace([periodPlaceholder,spacePlaceholder], ["."," "], $val);
if ( $val != $newval) $arr[$key]=$newval;
}
}
unset($val);
foreach($arr as $key=>$val) {
$newkey = str_replace([periodPlaceholder,spacePlaceholder], ["."," "], $key);
if ( str_contains($newkey, '_') ) {
// periode of space or [ or ] converted to _. Restore with querystring
$regex = '/&('.str_replace('_', '[ \.\[\]]', preg_quote($newkey, '/')).')=/';
$matches = null ;
if ( preg_match_all($regex, "&".urldecode($querystr), $matches) ) {
if ( count(array_unique($matches[1])) === 1 && $key != $matches[1][0] ) {
$newkey = $matches[1][0] ;
}
}
}
if ( $newkey != $key ) $arr = array_replace_key($arr,$key, $newkey);
if ( is_array($val)) {
sanitizeArr($arr[$newkey], $querystr);
}
}
}
function array_replace_key($array, $oldKey, $newKey): array {
// preserves order of the array
if( ! array_key_exists( $oldKey, $array ) ) return $array;
$keys = array_keys( $array );
$keys[ array_search( $oldKey, $keys ) ] = $newKey;
return array_combine( $keys, $array );
}
First replaces spaces and . by placeholders in querystring before coding before parsing, later undoes that within the array keys and values. This way we can use the normal parse_str.
Unmatched [ and ] are also replaced by underscores by parse_str, but these cannot be reliably replaced by a placeholder. And we definitely don't want to replace matched []. Hence we don't replace [ and ], en let them be replaced by underscores by parse_str. Then we restore the _ in the resulting keys and seeing in the original querystring if there was a [ or ] there.
Known bug: keys 'something]something' and almost identical 'something[something' may be confused. It's occurrence will be zero, so I left it.
Test:
var_dump(parse_str_clean("code.1=printr%28hahaha&code 1=448044&test.mijn%5B%5D%5B2%5D=test%20Roemer&test%20mijn%5B=test%202e%20Roemer"));
yields correctly
array(4) {
["code.1"]=>
string(13) "printr(hahaha"
["code 1"]=>
string(6) "448044"
["test.mijn"]=>
array(1) {
[0]=>
array(1) {
[2]=>
string(11) "test Roemer"
}
}
["test[mijn"]=>
string(14) "test 2e Roemer"
}
whereas the original parse_str only yields, with the same string:
array(2) {
["code_1"]=>
string(6) "448044"
["test_mijn"]=>
string(14) "test 2e Roemer"
}

How to use php array+string in html?

I am using PL/pgsql RETURNS TABLE to get the below output using pg_fetch_all in PHP
array(4) {
[0]=> array(1)
{ ["not_actual_values"]=> string(88) "("var1","var2",var3,var4,date1,int,int,int,var5,int,int,int,int)" }
[1]=> array(1)
{ ["not_actual_values"]=> string(89) "("var1","var2",var3,var4,date1,int,int,int,var5,int,int,int,int)" }
[2]=> array(1)
{ ["not_actual_values"]=> string(88) "("var1","var2",var3,var4,date1,int,int,int,var5,int,int,int,int)" }
[3]=> array(1)
{ ["not_actual_values"]=> string(89) "("var1","var2",var3,var4,date1,int,int,int,var5,int,int,int,int)" }
}
I am unable to use the above output in HTML. I tried using php explode but it didnt work I got zero array. Also, What confuses me I am getting quotes in first two variable and not in others.
Update
I used below function but I got zero array
function pgArrayToPhp($text) {
if(is_null($text)) {
return array();
} else if(is_string($text) && $text != '{}') {
$text = substr($text, 1, -1);// Removes starting "{" and ending "}"
if(substr($text, 0, 1) == '"') {
$text = substr($text, 1);
}
if(substr($text, -1, 1) == '"') {
$text = substr($text, 0, -1);
}
// If double quotes are present, we know we're working with a string.
if(strstr($text, '"')) { // Assuming string array.
$values = explode('","', $text);
} else { // Assuming Integer array.
$values = explode(',', $text);
}
$fixed_values = array();
foreach($values as $value) {
$value = str_replace('\\"', '"', $value);
$fixed_values[] = $value;
}
return $fixed_values;
} else {
return array();
}
}
How can i do this ?
Your inner values are arrays, not strings, you need to take that into account:
function pgArraytoPhp($array) {
foreach ($array as $row) { // $row is an inner array here!
actuallyDoParsing($row[0]); // Parse row's first element,
// which will be the string you want.
}
}
Depending on what you need, you'll return the accumulated result of all of those actuallyDoParsing() calls.
This is the answer that I have come up with. Though it is not neat but it seems to be working as expected now
$fetch=pg_fetch_all($query); //fetching data from postgresql
$count=count($fetch);
for ($j=0;$j<$count;$j++) {
$a = $fetch[$j]['not_actual_values'];
$b = array(explode("," , $a));
$count2=count($b[0]);
foreach ($b as $f) { echo '<tr>';
for ($i=0;$i<$count2;$i++){
echo '<td><input type="text" readonly value='.$f[$i].'>';
} } }
But now the problem is raw data contains noise as in "(" so that is spoiling the output.
Thank you all for your efforts.

print an array as code

I want to convert a big yaml file to PHP array source code. I can read in the yaml code and get back a PHP array, but with var_dump($array) I get pseudo code as output. I would like to print the array as valid php code, so I can copy paste it in my project and ditch the yaml.
You're looking for var_export.
You could use var_export, serialize (with unserialize on the reserving end), or even json_encode (and use json_decode on the receiving end). The last one has the advantage of producing output that can be processed by anything that can handle JSON.
Don't know why but I could not find satisfying code anywhere.
Quickly wrote this. Let me know if you find any errors.
function printCode($array, $path=false, $top=true) {
$data = "";
$delimiter = "~~|~~";
$p = null;
if(is_array($array)){
foreach($array as $key => $a){
if(!is_array($a) || empty($a)){
if(is_array($a)){
$data .= $path."['{$key}'] = array();".$delimiter;
} else {
$data .= $path."['{$key}'] = \"".htmlentities(addslashes($a))."\";".$delimiter;
}
} else {
$data .= printCode($a, $path."['{$key}']", false);
}
}
}
if($top){
$return = "";
foreach(explode($delimiter, $data) as $value){
if(!empty($value)){
$return .= '$array'.$value."<br>";
}
};
return $return;
}
return $data;
}
//REQUEST
$x = array('key'=>'value', 'key2'=>array('key3'=>'value2', 'key4'=>'value3', 'key5'=>array()));
echo printCode($x);
//OUTPUT
$array['key'] = 'value';
$array['key2']['key3'] = 'value2';
$array['key2']['key4'] = 'value3';
$array['key2']['key5'] = array();
Hope this helps someone.
An other way to display array as code with indentation.
Tested only with an array who contain string, integer and array.
function bo_print_nice_array($array){
echo '$array=';
bo_print_nice_array_content($array, 1);
echo ';';
}
function bo_print_nice_array_content($array, $deep=1){
$indent = '';
$indent_close = '';
echo "[";
for($i=0; $i<$deep; $i++){
$indent.=' ';
}
for($i=1; $i<$deep; $i++){
$indent_close.=' ';
}
foreach($array as $key=>$value){
echo "<br>".$indent;
echo '"'.$key.'" => ';
if(is_string($value)){
echo '"'.$value.'"';
}elseif(is_array($value)){
bo_print_nice_array_content($value, ($deep+1));
}else{
echo $value;
}
echo ',';
}
echo '<br>'.$indent_close.']';
}

Convert a String to Variable

I've got a multidimensional associative array which includes an elements like
$data["status"]
$data["response"]["url"]
$data["entry"]["0"]["text"]
I've got a strings like:
$string = 'data["status"]';
$string = 'data["response"]["url"]';
$string = 'data["entry"]["0"]["text"]';
How can I convert the strings into a variable to access the proper array element? This method will need to work across any array at any of the dimensions.
PHP's variable variables will help you out here. You can use them by prefixing the variable with another dollar sign:
$foo = "Hello, world!";
$bar = "foo";
echo $$bar; // outputs "Hello, world!"
Quick and dirty:
echo eval('return $'. $string . ';');
Of course the input string would need to be be sanitized first.
If you don't like quick and dirty... then this will work too and it doesn't require eval which makes even me cringe.
It does, however, make assumptions about the string format:
<?php
$data['response'] = array(
'url' => 'http://www.testing.com'
);
function extract_data($string) {
global $data;
$found_matches = preg_match_all('/\[\"([a-z]+)\"\]/', $string, $matches);
if (!$found_matches) {
return null;
}
$current_data = $data;
foreach ($matches[1] as $name) {
if (key_exists($name, $current_data)) {
$current_data = $current_data[$name];
} else {
return null;
}
}
return $current_data;
}
echo extract_data('data["response"]["url"]');
?>
This can be done in a much simpler way. All you have to do is think about what function PHP provides that creates variables.
$string = 'myvariable';
extract(array($string => $string));
echo $myvariable;
done!
You can also use curly braces (complex variable notation) to do some tricks:
$h = 'Happy';
$n = 'New';
$y = 'Year';
$wish = ${$h.$n.$y};
echo $wish;
Found this on the Variable variables page:
function VariableArray($data, $string) {
preg_match_all('/\[([^\]]*)\]/', $string, $arr_matches, PREG_PATTERN_ORDER);
$return = $arr;
foreach($arr_matches[1] as $dimension) { $return = $return[$dimension]; }
return $return;
}
I was struggling with that as well,
I had this :
$user = array('a'=>'alber', 'b'=>'brad'...);
$array_name = 'user';
and I was wondering how to get into albert.
at first I tried
$value_for_a = $$array_name['a']; // this dosen't work
then
eval('return $'.$array_name['a'].';'); // this dosen't work, maybe the hoster block eval which is very common
then finally I tried the stupid thing:
$array_temp=$$array_name;
$value_for_a = $array_temp['a'];
and this just worked Perfect!
wisdom, do it simple do it stupid.
I hope this answers your question
You would access them like:
print $$string;
You can pass by reference with the operator &. So in your example you'll have something like this
$string = &$data["status"];
$string = &$data["response"]["url"];
$string = &$data["entry"]["0"]["text"];
Otherwise you need to do something like this:
$titular = array();
for ($r = 1; $r < $rooms + 1; $r ++)
{
$title = "titular_title_$r";
$firstName = "titular_firstName_$r";
$lastName = "titular_lastName_$r";
$phone = "titular_phone_$r";
$email = "titular_email_$r";
$bedType = "bedType_$r";
$smoker = "smoker_$r";
$titular[] = array(
"title" => $$title,
"first_name" => $$firstName,
"last_name" => $$lastName,
"phone" => $$phone,
"email" => $$email,
"bedType" => $$bedType,
"smoker" => $$smoker
);
}
There are native PHP function for this:
use http://php.net/manual/ru/function.parse-str.php (parse_str()).
don't forget to clean up the string from '"' before parsing.
Perhaps this option is also suitable:
$data["entry"]["0"]["text"];
$string = 'data["entry"]["0"]["text"]';
function getIn($arr, $params)
{
if(!is_array($arr)) {
return null;
}
if (array_key_exists($params[0], $arr) && count($params) > 1) {
$bf = $params[0];
array_shift($params);
return getIn($arr[$bf], $params);
} elseif (array_key_exists($params[0], $arr) && count($params) == 1) {
return $arr[$params[0]];
} else {
return null;
}
}
preg_match_all('/(?:(\w{1,}|\d))/', $string, $arr_matches, PREG_PATTERN_ORDER);
array_shift($arr_matches[0]);
print_r(getIn($data, $arr_matches[0]));
P.s. it's work for me.

Categories