Convert a String to Variable - php

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.

Related

php access to specific position of multidimensional array by its keys and set it

In PHP we can do things like these:
Class Example {
...
}
$example = 'Example';
$object = new $example();
Or the use of variable variables:
$hour = 18;
$greets = array('Good morning','Good afternoon','Good evening');
$values = array(13,21,23);//people is sleeping at 23PM, so they don't greet.
$n = count($values);
$greet = 'greets';
for($i=0;$i<$n;$i++){
if($hour < $values[$i]){
echo 'hello, '.${$greet}[$i];
break;
}
}
And others..
I wonder if it would be possible to access directly to a specific index of a multidimensional array in a similar way. Something like:
$array = array(...); //multidimensional array.
$position = '[0][4][3]';
print_r($array$position);
Thanks in advance.
UPDATE
I'm so sorry because I finished my question in a wrong way.
I need to set the multimesional array and add a value. i.e:
$array$position = $data;
You could implement it yourself with a custom function:
function getValueFromMultiDimensionalArray( array $array, string $key )
{
$keys = explode('][', $key);
$value = $array;
foreach ($keys as $theKey) {
// remove the opening or closing bracket if present
$theKey = str_replace([ '[', ']' ], '', $theKey);
if (!isset($value[$theKey])) {
return null;
}
$value = $value[$theKey];
}
return $value;
}
You can define path as dot separated , check the following solution
function getValueByKey($a,$p){
$c = $a;
foreach(explode('.',$p) as $v){
if(!array_key_exists($v, $c)) return null;
$c = $c[$v];
}
return $c;
}
You can use this function as
$path = '1.2.3.0';
$indexValue = getValueByKey($array, $path);
Nope, this is not possible.
The only thing you can do is to implement ArrayAccess interface, which allows to access instances with [] operator. But you will have to define the logic yourself.
class MyClass implements ArrayAccess
{
...
}
$x = new MyClass([0=>[4=>[3=>'hello world']]]);
$position = '[0][4][3]';
echo $x[$position]; //hello world

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.

Creating a function from a variable

I am attempting to run a function named from a variable. There is no syntax error. Temperature is not returned. I don't know for certain if the problem is with the function itself or the eval. Variations on the eval theme have not worked so far.
function getBtemp($lum, $sub){
$tempsB = array(
"V" => array( 30000, 25400, ... ),
"III" => array( 29000, 24000, ... ),
"I" => array( 26000, 20800, ... ) );
if($lum == "VI"){ $lum = "V"; }
else if($lum == "IV"){ $lum = "III"; }
else if($lum == "II" || $lum == "Ib" || $lum == "Ia" ){ $lum = "V"; }
return $tempsB['$lum']['$sub']; }
// Variables:
$spectralclass = "B";
$luminosityclass = "V";
$subclass = 5;
// Needed:
$temp = getBtemp($luminosityclass, $subclass);
// Functions are named from spectral class, e.g. get.$spectralclass.temp()
// Attempt:
$str = "$temp = get".$spectralclass."temp($luminosityclass, $subclass);";
eval($str);
Try doing this:
$func = 'get'.$spectralclass.'temp';
$temp = $func($luminosityclass, $subclass);
You might be better off doing something like
$functionName = 'get' . $spectralclass . 'temp';
$temp = $functionName($luminosityclass, $subclass);
This is what the PHP manual calls a "variable function". In most cases PHP lets you treat a string variable as a function name, and doing so is a bit safer (more restrictive, less error-prone) than eval.
You need to pass parameters after set function name. See a sample:
function getAtemp($a = 'default') {
echo $a;
}
$name = 'Trest';
$function = 'A';
$temp = 'get' . $function . 'temp';
echo($temp('teste'));
Additionally, read from Eric Lippert: Eval is Evil
Replace the following line:
$str = "$temp = get".$spectralclass."temp($luminosityclass, $subclass);";
by
$str = '$temp = get'.$spectralclass.'temp($luminosityclass, $subclass);';
or
$str = "\$temp = get".$spectralclass."temp(\$luminosityclass, \$subclass);";
See http://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.double

Convert string to array value in PHP

If I had an array such as:
testarray = array('foo'=>34, 'bar'=>array(1, 2, 3));
How would I go about converting a string such as testarray[bar][0] to find the value its describing?
Well, you can do something like this (Not the prettiest, but far safer than eval)...:
$string = "testarray[bar][0]";
$variableBlock = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*';
$regex = '/^('.$variableBlock.')((\[\w+\])*)$/';
if (preg_match($regex, $string, $match)) {
$variableName = $match[1]; // "testarray"
if (!isset($$variableName)) {
//Error, the variable does not exist
return null;
} else {
$array = $$variableName;
if (preg_match_all('/\[(\w+)\]/', $match[2], $matches)) {
foreach ($matches[1] as $match) {
if (!is_array($array)) {
$array = null;
break;
}
$array = isset($array[$match]) ? $array[$match] : null;
}
}
return $array;
}
} else {
//error, not in correct format
}
You could use PHP's eval function.
http://php.net/manual/en/function.eval.php
However, make absolutely sure the input is sanitized!
Cheers

PHP array as variable name

How to send an indexes name for php array vairable.
the array is
$array = array('Somthing'=>array('More'=>array('id'=> 34)));
and now I want to display this thing but with a variable name I don't know how to explain so I write what I want to have.
$index_name = '[Something][More][id]';
$array{$index_name};
Is it possible in any way ?
Not in one go like that. Here's how you'd do it:
$array['Something']['More']['id']
If you particularly wanted access multidimensional arrays with a single string, then you could build a function to do that:
function array_multi(Array $arr, $path) {
$parts = explode(".", $path);
$curr =& $arr;
for ($i = 0, $l = count($parts); $i < $l; ++$i) {
if (!isset($curr[$parts[$i]])) {
// path doesn't exist
return null;
} else if (($i < $l - 1) && !is_array($curr[$parts[$i]]) {
// path doesn't exist
return null;
}
$curr =& $curr[$parts[$i]];
}
return $curr;
}
// usage:
echo array_multi($array, "Something.More.id"); // 34
echo array_multi($array, "Something.More"); // array("id" => 34)
Recursive version supporting your syntax with square brackets:
$array = array('Something'=>array('More'=>array('id'=> 34)));
$string = '[Something][More][id]';
echo scan_array($string, $array);
function scan_array($string, $array) {
list($key, $rest) = preg_split('/[[\]]/', $string, 2, PREG_SPLIT_NO_EMPTY);
if ( $key && $rest ) {
return scan_array($rest, $array[$key]);
} elseif ( $key ) {
return $array[$key];
} else {
return FALSE;
}
}
Ok, I know this is how people get shot. But c'mon, eval() is not always the wrong answer.
$array = array('Something'=>array('More'=>array('id'=> 34)));
$index_name = '[Something][More][id]';
eval('$val = $array'.$index_name.';'); // Wrap in a function or something
You could do this with eval():
<?php
$array = array('Somthing'=>array('More'=>array('id'=> 34)));
$index_name = "['Somthing']['More']['id']";
$stmt='echo $array'.$index_name.';';
eval($stmt);
?>
UPDATE:
It seems some SO users are uncomfortable with the idea of using eval(). I think it makes sense to read this thread which discusses the pros and cons before deciding whether to use this in your own code.
If you've cornered yourself into needing to do something like this, there's a pretty good chance you've done something else in a poor way. There's valid reasons to do this, but not very often.
function key_path($arr, $keys) {
return $keys ? key_path($arr[array_shift($keys)], $keys) : $arr;
}
$arr['Something']['More']['id'] = 34;
$keys = array('Something', 'More', 'id');
var_dump( key_path($arr, $keys));

Categories