Get array value using a string as the array name and indexes - php

I am trying to send specific indexes from arrays by string to some php code to describe the data that I need to combine. The problem I am having is that SESSION does not seem to be available within the function Str_To_Array. What am I missing about scope here? Also if anybody can recommend a better way I would be every so grateful. PS i added the include in case including the function causes any abnormalities.
function Str_To_Array($str) {
$d = explode(':',$str) ;
print_r($d[0]) ;
$t = $d[0] ;
$n = $$t ;
if( !isset( $d[1] ) ) { return $n ; }
$n = $n[$d[1]] ;
return $n ;
}
include(DIR_ROOT . "php_function/Str_To_Array.php") ;
$test = '_SESSION' ;
$ARRANGE = Str_To_Array($test) ;<----this says _SESSION is undefined
print_r($ARRANGE) ;
$ARRANGE = $$test ;<----this works
print_r($ARRANGE) ;

It loos like it's the problem of PHP, just tried the code below, when in a function, ${'_SESSION'} works and $$t don't work. This only happens to $_SESSION but not the other super global $_POST and $_GET etc.
<?php
session_start();
function foo() {
$t = '_SESSION';
$a = $$t; // not work
$b = ${'_SESSION'}; // works
var_dump($a, $b);
}
foo();

Hard to follow the purpose here, however this should work
function getVar($str)
{
$vars = get_defined_vars();
$d = explode(':',$str) ;
if (isset($vars[$d[0]]) || array_key_exists($vars[$d[0]])) {
if (!empty($d[1]) && (isset($vars[$d[0]][$d[1]]) || array_key_exists($vars[$d[0]][$d[1]]))
return $vars[$d[0]][$d[1]];
return $vars[$d[0]];
}
return null;
}

Related

Function returns empty array

I'm attempting to pass the denominator variable to the function convert. When I do, the returned array "$new_arr" produces "0" for each value.
I have tried replacing the variable $denominator with a digit within the function and the new array returns with the appropriate numbers.
My experience with PHP is novice so my questions are:
1) Is this an issue of scoping? I thought by declaring these variables outside of the function, they were inherently global.
2) Do I need to pass '$denominator' as an argument as well?
Thanks in advance. Here's the code.
$highest_val = max($array_1);
$lowest_val = min($array_2);
$denominator = $highest_val - $lowest_val;
function convert($arr)
{
$new_arr=array();
for($i=0, $count = count($arr); $i<$count; $i++)
{
$numerator = $arr[$i]-$lowest_val;
$calc = $numerator/$denominator;
$new_arr[] .= $calc;
}
$arr = $new_arr;
return $arr;
}
$test_arr = convert($open_array);
var_dump($test_arr);
To use Global variables inside your function, you need to define them global there too. Like this
$highest_val = max($array_1);
$lowest_val = min($array_2);
$denominator = $highest_val - $lowest_val;
function convert($arr)
{
global $highest_val;
global $lowest_val ;
global $denominator;
Or you can simply send those three values as parameters to your function. You can also use $GLOBALS array if you follow the global scope path
Yes, you do need to pass in the values as parameters into the function.
function convert($arr, $highest_val, $lowest_val, $denominator) { ... }
$test_arr = convert($open_array, $highest_val, $lowest_val, $denominator);
var_dump($test_arr);

PHP Notice: Undefined property: Tpl::$lbName

I have a class Tpl to mount template with this function (template.php)
function Set($var, $value){
$this->$var = $value;
}
A php file that call the function, example (form.php):
$t->Set("lbAddress","Address");
And a html file with the template with tags (template.html)
<tr><td>[lbAdress]</td></tr>
To print the html I have this function (template.php) - the notice points to this function
function Show_Temp($ident = ""){
// create array
$arr = file($this->file);
if( $ident == "" ){
$c = 0;
$len = count($arr);
while( $c < $len ){
$temp = str_replace("[", "$" . "this->", $arr[$c]);
$temp = str_replace("]", "", $temp);
$temp = addslashes($temp);
eval("\$x = \"$temp\";");
echo $x;
$c++;
}
} else {
$c = 0;
$len = count($arr);
$tag = "*=> " . $ident;
while( $c < $len ){
if( trim($arr[$c]) == $tag ){
$c++;
while( (substr(#$arr[$c], 0 ,3) != "*=>" ) && ($c < $len) ){
$temp = str_replace("[", "$" . "this->", $arr[$c]);
$temp = str_replace("]", "", $temp);
$temp = addslashes($temp);
eval("\$x= \"$temp\";"); //this is the line 200
echo $x;
$c++;
}
$c = $len;
}
$c++;
}
}
}
If the template .html have a line [lbName] and I don't have the line $t->Set("lbName","Name"); at the php code, I receive the error PHP Notice: Undefined property: Tpl::$lbName in ../template.php(200) : eval()'d code on line 1. The solution that I found is add lines like $t->Set("lbName","");, but if I have 50 tags in HTML that I don't use in PHP, I have to add all 50 $t->Set("tag_name","");. The error occurred after migrate to the PHP 5.
Can someone help me? Thanks
Perhaps a better way still would be not to rely on dynamic evaluation through eval (it's generally best to avoid eval where possible), but to replace [lbName] with the value stored in the object directly as and when needed. If you can replace [lbName] with $this->lbName, surely you can also replace it with the value of lBName that you've looked up on-the-fly?
To answer your original question, however:
If I understand correctly, you're setting the values like this:
$t->Set('foo', 'bar');
And – effectively – getting them like this:
$t->foo;
If so, you could implement a __get method to intercept the property references and provide your own logic for retrieving the value; e.g.:
public function __get($key)
{
// You can adapt this logic to suit your needs.
if (isset($this->$key))
{
return $this->$key;
}
else
{
return null;
}
}
In this case, you'd probably be better off using an associative array as the backing store, and then using __get and __set to access it; e.g.:
class Template
{
private $values = array();
public function __get($key)
{
if (array_key_exists[$key, $this->values])
{
return $this->values[$key];
}
else
{
return null;
}
}
public function __set($key, $value)
{
$this->values[$key] = $value;
}
}

PHP each and static array declaration

So, I've written some rather convoluted 'functional' PHP code to perform folding on an array. Don't worry, I won't use it anywhere. The problem is, PHP's 'each' function only seems to go as far as the end of an array as it is statically (actually, see bottom) declared.
// declare some arrays to fold with
$six = array("_1_","_2_","_3_","_4_","_5_","_6_");
// note: $ns = range(0,100) won't work at all--lazy evaluation?
$ns = array(1,2,3,4,5,6,7,8);
$ns[8] = 9; // this item is included
// add ten more elements to $ns. each can't find these
for($i=0; $i<10; ++$i)
$ns[] = $i;
// create a copy to see if it fixes 'each' problem
$ms = $ns;
$ms[0] = 3; // Just making sure it's actually a copy
$f = function( $a, $b ) { return $a . $b; };
$pls = function( $a, $b ) { return $a + $b; };
function fold_tr( &$a, $f )
{
$g = function ( $accum, &$a, $f ) use (&$g)
{
list($dummy,$n) = each($a);
if($n)
{
return $g($f($accum,$n),$a,$f);
}
else
{
return $accum;
}
};
reset($a);
return $g( NULL, $a, $f );
}
echo "<p>".fold_tr( $six, $f )."</p>"; // as expected: _1__2__3__4__5__6_
echo "<p>".fold_tr( $ns, $pls )."</p>"; // 45 = sum(1..9)
echo "<p>".fold_tr( $ms, $pls )."</p>"; // 47 = 3 + sum(2..9)
I honestly have no clue how each maintains its state; it seems vestigial at best, since there are better (non-magical) mechanisms in the language for iterating through a list, but does anyone know why it would register items added to an array using $a[$index] = value but not '$a[] = value`? Thanks in advance any insight on this behavior.
Your loop is exiting early thanks to PHP's weak typing:
if($n)
{
return $g($f($accum,$n),$a,$f);
}
else
{
return $accum;
}
when $n is 0 (e.g. $ns[9]), the condition will fail and your loop will terminate. Fix with the following:
if($n !== null)

PHP, isset and how to get rid of repetitive chains of variables?

I have strict error reporting. I have to use isset and it make me to write long, repetitive chains of variables in PHP. I have sometimes to write code like this:
if (isset($my_object->an_array[$a_variable])):
$other_variable = $my_object->an_array[$a_variable];
else:
$other_variable = false;
endif;
or
if (isset($my_object->an_array[$a_variable])):
return $my_object->an_array[$a_variable];
endif;
Sometimes it is longer and more complicated. It isn't readable and take too much time to type. I'd like to get rid of it.
The question
Is there a way to write $my_object->an_array[$a_variable] only once?
You can write functions to encapsulate repetitive code:
function get_variable(array $array, $variable_name, $default_value=FALSE){
if( isset($array[$variable_name]) ){
return $array[$variable_name];
}else{
return $default_value;
}
}
Tweak to your needs.
In the end I have found two solutions.
I. There is operator # in PHP. It is very dangerous, tough.
http://www.php.net/manual/en/language.operators.errorcontrol.php
However, it is acceptable in my situation.
This is not a fatal error.
The value of undefined variable is defined as null. I'm fine with testing for this or using implicit conversions.
I can use $php_errormsg in extreme situations.
The code example:
$tmp = $false_object->property->property; #Throw notice
$tmp = $false_array['a_field']['a_field']; #Throw notice
$tmp = #$false_object->property->property; #Quiet
$tmp = #$false_array['a_field']['a_field']; #Quiet
echo $php_errormsg; #I can print that notice
The downside is I don't receive information about lack of quotes in brackets.
$a = array('e'=>false);
$tmp = $a[e]; #Throw notice
$tmp = #$a[e]; #Quiet
echo $php_errormsg; #This variable still works
II. It is possible to use operator &.
The value of undefined variable will be NULL too.
The $php_errormsg variable doesn't work for undefined variables.
I get notice for lack of quotes in brackets, though.
The code example:
$tmp = $false_object->property->property; #Throw notice
$tmp = $false_array['a_field']['a_field']; #Throw notice
$tmp = &$false_object->property->property; #Quiet
$tmp = &$false_array['a_field']['a_field']; #Quiet
var_dump($tmp); #NULL;
The lack of quotes problem:
$array = array('a_field'=>true);
$tmp = $array[a_field]; #Throw notice
$tmp = #$array[a_field]; #Quiet
$tmp = &$array[a_field]; #Throw notice
function check($var)
{
if(isset[$var])
return $var;
else
return "";
}
Then each time you need to do checking call like:
$other_b = check($b);
I doubt you will get any suggestions that you will consider satisfactory. The best I can suggest is this, and I would add that I consider it quite ugly:
function ifset ($var) {
return is_null($var) ? false : $var;
}
Having defined this function, you can call it like this:
$other_variable = ifset(#$my_object->an_array[$a_variable]);
Note that you need the error suppression operator here, because otherwise you'll get an undefined variable notice if the variable indeed doesn't exist. (The reason why you don't need it for isset() is that isset() is really a special parser token rather than an ordinary function.)
now i get the same problem. i must check it and then get it ,it's so ugrly.
so i write the function like this
function get_val($arr,$key,$default_val=false){
if(!is_array($arr)) return $default_val;
$idx = explode('>>',$key);
$tmp = $arr;
$catched = true;
foreach($idx as $index) {
if(!isset($tmp[$index])){
$catched = false;
break;
}else{
$tmp = $tmp[$index];
}
}
if($catched) $default_val = $tmp;
return $default_val;
}
//for example
$arr = array('k1'=>array('k2'=>array(1,'k22'=>22,'k23'=>array('k3'=>1))));
get_val($arr,'k1>>k2>>k23>>k3');
A method to extract those variables would probably be better in your case, then:
class MyObject
{
private $an_array;
public function __construct()
{
$this->an_array = array();
}
public function get( $key )
{
if(isset($this->an_array[$key]))
return $this->an_array[$key];
return false; //or empty string
}
public function set( $key, $value )
{
$this->an_array[$key] = $value;
}
}
That way, you can do it like this:
$my_object->get($a_variable]);
I use these little helper functions to access properties of (multidimensional) arrays/objects without writing repetitive isset() statements. They might not be the fastest running solution, but they are very comfortable:
// AI(data,1,default) === data[1] or default
function AI( $a, $i, $d=null ){
if( is_array ($a)){ if( array_key_exists( $i, $a )) return $a[ $i ]; return $d; }
if( is_object($a)){ if( property_exists( $a, $i )) return $a -> $i; return $d; }
return $d;
}
// AII(data,1,2,3) === data[1][2][3] or null
function AII( $o ){
$a = func_get_args();
$al = func_num_args();
for( $i=1; $i < $al; $i++ ){
$k = $a[$i];
if( is_array ($o) && array_key_exists($k,$o)) $o =& $o[ $k ];
else if( is_object($o) && property_exists ($o,$k)) $o =& $o -> $k;
else return null; // nothing to access
}
return $o;
}
// AIID(data,1,2,3,default) == data[1][2][3] or default
function AIID( $o ){
$a = func_get_args();
$default = end( $a );
$al = count( $a ) - 1;
for( $i=1; $i < $al; $i++ ){
$k = $a[$i];
if( is_array ($o) && array_key_exists($k,$o)) $o =& $o[ $k ];
else if( is_object($o) && property_exists ($o,$k)) $o =& $o -> $k;
else return $default;
}
return $o;
}
// AAID(data,[1,2,3],default) == data[1][2][3] or default
function AAID( $o, $a, $default = null ){
foreach( $a as $k ){
if( is_array ($o) && array_key_exists($k,$o)) $o =& $o[ $k ];
else if( is_object($o) && property_exists ($o,$k)) $o =& $o -> $k;
else return $default;
}
return $o;
}

How Can I get the string that present the variable in function argument?

How Can I get the string that present the variable in function argument?
example
function dbg($param){
return "param";
}
$var="Hello World";
echo dgb($var);
output: var
$arr=array();
echo dgb($arr);
output: arr
It is NOT possible to do what you ask reliably.
The closest you can come up to doing that is to do a debug_backtrace() to check which file called the function then tokenize the source of that file to find the reference.
Again, this will not work reliably. It will fail if you have multiple calls on one line. Truthfully, it isn't work the trouble. You are writing the code anyway, you know which variable you are passing.
function dbg($var) {
$bt = debug_backtrace();
$file = $bt[0]['file'];
$line = $bt[0]['line'];
$source = file_get_contents($file);
$tmpTokens = token_get_all($source);
$tokens = array ();
foreach ($tmpTokens as $token) {
if (is_array($token) && $token[0] !== T_INLINE_HTML && $token[0] !== T_WHITESPACE) {
$tokens[] = $token;
}
}
unset($tmpTokens);
$countTokens = count($tokens);
for ($i = 0; $i < $countTokens; $i++) {
if ($tokens[$i][3] > $line || $i === $countTokens - 1) {
$x = $i - (($tokens[$i][3] > $line) ? 1 : 0);
for ($x; $x >= 0; $x--) {
if ($tokens[$x][0] === T_STRING && $tokens[$x][1] === __FUNCTION__) {
if ($x !== $countTokens - 1 && $tokens[$x + 1][0] === T_VARIABLE) {
return $tokens[$x + 1][1];
}
}
}
}
}
return null;
}
printing a variable, you're doing it wrong.
the right ways is like this:
function dbg($param){
return $param;
}
$var="Hello World";
echo dgb($var);
and by the way you're passing an array to a function that only accepts variables. and oh it's a null array all the way worse!
I'm just guessing that you're trying to make a custom debugger which as a nice touch prints the name of the variable you're debugging. Well, that's not really possible. I'd suggest you look at debug_backtrace, which allows you to print the file, line number, function name and arguments of the place where you invoked your dbg function. Unless you use dbg more than once per line that helps you find the information you're looking for, and IMO is a lot more useful anyway.
Alternatively, you can have both the name and value of your variable if you call your function like this:
function dbg($var) {
echo 'name: ' . key($var) . ', value: ' . current($var);
}
$foo = 'bar';
dbg(compact('foo'));
You question doesnt make much sense, you may want to reword it.
It sounds like you want to use the $param in the function in which case you can just do something link echo $param;

Categories