Get variables in scope at each PHP backtrace level? - php

Is there a way to view the variables set in each stack frame in a backtrace? I can come pretty close with a combination of debug_backtrace(true) to get the objects, get_object_vars on each object to get $this vars, the args key in each backtrace frame, and get_defined_vars to get globals, but any temporary variables set within a function I can't find a way to retrieve.
Here's an example situation:
function method1($foo) {
$temp = method2($foo + 1);
foreach ($temp as $t) {
method2($t);
}
}
function method2($bar) {
$temp2 = $bar->value + $_GET['val'];
debug();
}
function debug() {
// to be created
$global_scope = get_defined_vars();
$bt = debug_backtrace(true);
}
I can get $foo and $bar via the args key in the backtrace, the object variables of $bar through get_object_vars, and the globals through get_defined_vars. I want to get the value of $temp2 and $temp as well.

Install and Enable XDebug on your (local) server. Then use xdebug_get_declared_vars(). Make sure that you set xdebug.collect_vars to On in your xdebug .ini file.
Example:
<?php
class strings {
static function fix_strings($a, $b) {
foreach ($b as $item) {
}
var_dump(xdebug_get_declared_vars());
}
}
strings::fix_strings(array(1,2,3), array(4,5,6));
?>
Returns:
array
0 => string 'a' (length=1)
1 => string 'b' (length=1)
2 => string 'item' (length=4)
Example from xdebug.org
Note, that the function only returns variables in the scope where the function xdebug_get_declared_vars() is called in.

Alter your debug to take 1 param. Then just pass in get_defined_vars. This will give you an array of all the vars in the local scope.

Related

Configuration class - Get configuration array from the function string argument

I have a function like this:
$conf = array ('test_value' => 1, 'test_value2' => 2);
function GetValueArray($array, $value)
{
return $array[$value];
}
Im using this function to receive a value from an array. My problem is that i cannot use this function like this:
GetValueArray('conf', 'test_value');
How could i convert 'conf' to the real array named conf to receive my 'test_value'?
Because functions have their own scope, be sure to 'globalize' the variable that you're looking into.
But as Rizier123 said, you can use brackets around a variable to dynamically get/set variables.
<?php
$conf = array ('test_value' => 1, 'test_value2' => 2);
function GetValueArray($array, $value)
{
global ${$array};
return ${$array}[$value];
}
echo GetValueArray('conf', 'test_value'); // echos '1'
echo GetValueArray('conf', 'test_value2'); // echos '2'
?>

PHP reference variable by case-insensitive string

PHP 5. I'm in a situation where I need to translate a case-insensitive url query to member variables in a PHP object. Basically, I need to know what member variable the url query key points to so I can know if it's numeric or not.
For example:
class Foo{
$Str;
$Num;
}
myurl.com/stuff?$var=value&num=1
When processing this URL query, I need to know that "str" associates with Foo->$Str, etc. Any ideas on how to approach this? I can't come up with anything.
Try something like this.
function fooHasProperty($foo, $name) {
$name = strtolower($name);
foreach ($foo as $prop => $val) {
if (strtolower($prop) == $name) {
return $prop;
}
}
return FALSE;
}
$foo = new Foo;
// Loop through all of the variables passed via the URL
foreach ($_GET as $index => $value) {
// Check if the object has a property matching the name of the variable passed in the URL
$prop = fooHasProperty($foo, $index);
// Object property exists already
if ($prop !== FALSE) {
$foo->{$prop} = $value;
}
}
And it may help to take a look at php's documentation on Classes and Objects.
Example:
URL: myurl.com/stuff?var=value&num=1
Then $_GET looks like this:
array('var' => 'value', 'num' => '1')
Looping through that, we would be checking if $foo has a property var, ($foo->var) and if it has a property num ($foo->num).

php function to unset variables passed by reference

currently i'm using this php function :
function if_exist(&$argument, $default = '')
{
if (isset ($argument))
{
echo $argument;
}
else
{
echo $default;
}
}
i want this function to unset the variables $argument(passed by reference) and $default just after echoing their value, how can i do this?
Thanks in advance.
According to the manual for unset:
If a variable that is PASSED BY REFERENCE is unset() inside of a
function, only the local variable is destroyed. The variable in the
calling environment will retain the same value as before unset() was
called.
I assume this is the issue you're encountering. So, my suggestion is to simply set $argument to NULL. Which, according to the NULL docs will "remove the variable and unset its value.".
For example:
$argument = NULL;
$default is passed by value, so it cannot be unset (except in the local scope).
As you undoubtedly discovered, unset() simply unsets the reference to $argument. You can (sort of) unset $argument like this:
$argument = null;
the only way to do this with a function is using globals.
//To unset() a global variable inside of a function,
// then use the $GLOBALS array to do so:
<?php
function foo()
{
unset($GLOBALS['bar']);
}
$bar = "something";
foo();
?>
If var is not array, and passed by reference, unset is actually unset the pointer, so it will not affect the original.
However if the var is array, you can unset its keys. eg:
$arr = [
'a' => 1,
'b' => ['c' => 3],
];
function del($key, &$arr) {
$key = explode('.', $key);
$end = array_pop($key);
foreach ($key as $k) {
if (is_array($arr[$k]) {
$arr = &$arr[$k];
} else {
return; // Error - invalid key -- doing nothing
}
}
unset($arr[$end]);
}
del('b.c', $arr); // $arr = ['a' => 1, 'b' => []]
del('b', $arr); // $arr = ['a' => 1]

PHP Constants Containing Arrays?

This failed:
define('DEFAULT_ROLES', array('guy', 'development team'));
Apparently, constants can't hold arrays. What is the best way to get around this?
define('DEFAULT_ROLES', 'guy|development team');
//...
$default = explode('|', DEFAULT_ROLES);
This seems like unnecessary effort.
Since PHP 5.6, you can declare an array constant with const:
<?php
const DEFAULT_ROLES = array('guy', 'development team');
The short syntax works too, as you'd expect:
<?php
const DEFAULT_ROLES = ['guy', 'development team'];
If you have PHP 7, you can finally use define(), just as you had first tried:
<?php
define('DEFAULT_ROLES', array('guy', 'development team'));
PHP 5.6+ introduced const arrays - see Andrea Faulds' answer.
You can also serialize your array and then put it into the constant:
# define constant, serialize array
define ("FRUITS", serialize (array ("apple", "cherry", "banana")));
# use it
$my_fruits = unserialize (FRUITS);
You can store them as static variables of a class:
class Constants {
public static $array = array('guy', 'development team');
}
# Warning: array can be changed lateron, so this is not a real constant value:
Constants::$array[] = 'newValue';
If you don't like the idea that the array can be changed by others, a getter might help:
class Constants {
private static $array = array('guy', 'development team');
public static function getArray() {
return self::$array;
}
}
$constantArray = Constants::getArray();
EDIT
Since PHP5.4, it is even possible to access array values without the need for intermediate variables, i.e. the following works:
$x = Constants::getArray()['index'];
If you are using PHP 5.6 or above, use Andrea Faulds answer
I am using it like this. I hope, it will help others.
config.php
class app{
private static $options = array(
'app_id' => 'hello',
);
public static function config($key){
return self::$options[$key];
}
}
In file, where I need constants.
require('config.php');
print_r(app::config('app_id'));
This is what I use. It is similar to the example provided by soulmerge, but this way you can get the full array or just a single value in the array.
class Constants {
private static $array = array(0 => 'apple', 1 => 'orange');
public static function getArray($index = false) {
return $index !== false ? self::$array[$index] : self::$array;
}
}
Use it like this:
Constants::getArray(); // Full array
// OR
Constants::getArray(1); // Value of 1 which is 'orange'
You can store it as a JSON string in a constant. And application point of view, JSON can be useful in other cases.
define ("FRUITS", json_encode(array ("apple", "cherry", "banana")));
$fruits = json_decode (FRUITS);
var_dump($fruits);
PHP 7+
As of PHP 7, you can just use the define() function to define a constant array :
define('ANIMALS', [
'dog',
'cat',
'bird'
]);
echo ANIMALS[1]; // outputs "cat"
I know it's a bit old question, but here is my solution:
<?php
class Constant {
private $data = [];
public function define($constant, $value) {
if (!isset($this->data[$constant])) {
$this->data[$constant] = $value;
} else {
trigger_error("Cannot redefine constant $constant", E_USER_WARNING);
}
}
public function __get($constant) {
if (isset($this->data[$constant])) {
return $this->data[$constant];
} else {
trigger_error("Use of undefined constant $constant - assumed '$constant'", E_USER_NOTICE);
return $constant;
}
}
public function __set($constant,$value) {
$this->define($constant, $value);
}
}
$const = new Constant;
I defined it because I needed to store objects and arrays in constants so I installed also runkit to php so I could make the $const variable superglobal.
You can use it as $const->define("my_constant",array("my","values")); or just $const->my_constant = array("my","values");
To get the value just simply call $const->my_constant;
Yes, You can define an array as constant. From PHP 5.6 onwards, it is possible to define a constant as a scalar expression, and it is also possible to define an array constant. It is possible to define constants as a resource, but it should be avoided, as it can cause unexpected results.
<?php
// Works as of PHP 5.3.0
const CONSTANT = 'Hello World';
echo CONSTANT;
// Works as of PHP 5.6.0
const ANOTHER_CONST = CONSTANT.'; Goodbye World';
echo ANOTHER_CONST;
const ANIMALS = array('dog', 'cat', 'bird');
echo ANIMALS[1]; // outputs "cat"
// Works as of PHP 7
define('ANIMALS', array(
'dog',
'cat',
'bird'
));
echo ANIMALS[1]; // outputs "cat"
?>
With the reference of this link
Have a happy coding.
Can even work with Associative Arrays.. for example in a class.
class Test {
const
CAN = [
"can bark", "can meow", "can fly"
],
ANIMALS = [
self::CAN[0] => "dog",
self::CAN[1] => "cat",
self::CAN[2] => "bird"
];
static function noParameter() {
return self::ANIMALS[self::CAN[0]];
}
static function withParameter($which, $animal) {
return "who {$which}? a {$animal}.";
}
}
echo Test::noParameter() . "s " . Test::CAN[0] . ".<br>";
echo Test::withParameter(
array_keys(Test::ANIMALS)[2], Test::ANIMALS["can fly"]
);
// dogs can bark.
// who can fly? a bird.
if you're using PHP 7 & 7+, you can use fetch like this as well
define('TEAM', ['guy', 'development team']);
echo TEAM[0];
// output from system will be "guy"
Using explode and implode function we can improvise a solution :
$array = array('lastname', 'email', 'phone');
define('DEFAULT_ROLES', implode (',' , $array));
echo explode(',' ,DEFAULT_ROLES ) [1];
This will echo email.
If you want it to optimize it more you can define 2 functions to do the repetitive things for you like this :
//function to define constant
function custom_define ($const , $array) {
define($const, implode (',' , $array));
}
//function to access constant
function return_by_index ($index,$const = DEFAULT_ROLES) {
$explodedResult = explode(',' ,$const ) [$index];
if (isset ($explodedResult))
return explode(',' ,$const ) [$index] ;
}
Hope that helps . Happy coding .
Doing some sort of ser/deser or encode/decode trick seems ugly and requires you to remember what exactly you did when you are trying to use the constant. I think the class private static variable with accessor is a decent solution, but I'll do you one better. Just have a public static getter method that returns the definition of the constant array. This requires a minimum of extra code and the array definition cannot be accidentally modified.
class UserRoles {
public static function getDefaultRoles() {
return array('guy', 'development team');
}
}
initMyRoles( UserRoles::getDefaultRoles() );
If you want to really make it look like a defined constant you could give it an all caps name, but then it would be confusing to remember to add the '()' parentheses after the name.
class UserRoles {
public static function DEFAULT_ROLES() { return array('guy', 'development team'); }
}
//but, then the extra () looks weird...
initMyRoles( UserRoles::DEFAULT_ROLES() );
I suppose you could make the method global to be closer to the define() functionality you were asking for, but you really should scope the constant name anyhow and avoid globals.
You can define like this
define('GENERIC_DOMAIN',json_encode(array(
'gmail.com','gmail.co.in','yahoo.com'
)));
$domains = json_decode(GENERIC_DOMAIN);
var_dump($domains);
Constants can only contain scalar values, I suggest you store the serialization (or JSON encoded representation) of the array.
If you are looking this from 2009, and you don't like AbstractSingletonFactoryGenerators, here are a few other options.
Remember, arrays are "copied" when assigned, or in this case, returned, so you are practically getting the same array every time. (See copy-on-write behaviour of arrays in PHP.)
function FRUITS_ARRAY(){
return array('chicken', 'mushroom', 'dirt');
}
function FRUITS_ARRAY(){
static $array = array('chicken', 'mushroom', 'dirt');
return $array;
}
function WHAT_ANIMAL( $key ){
static $array = (
'Merrick' => 'Elephant',
'Sprague' => 'Skeleton',
'Shaun' => 'Sheep',
);
return $array[ $key ];
}
function ANIMAL( $key = null ){
static $array = (
'Merrick' => 'Elephant',
'Sprague' => 'Skeleton',
'Shaun' => 'Sheep',
);
return $key !== null ? $array[ $key ] : $array;
}

How to get a variable name as a string in PHP?

Say i have this PHP code:
$FooBar = "a string";
i then need a function like this:
print_var_name($FooBar);
which prints:
FooBar
Any Ideas how to achieve this? Is this even possible in PHP?
I couldn't think of a way to do this efficiently either but I came up with this. It works, for the limited uses below.
shrug
<?php
function varName( $v ) {
$trace = debug_backtrace();
$vLine = file( __FILE__ );
$fLine = $vLine[ $trace[0]['line'] - 1 ];
preg_match( "#\\$(\w+)#", $fLine, $match );
print_r( $match );
}
$foo = "knight";
$bar = array( 1, 2, 3 );
$baz = 12345;
varName( $foo );
varName( $bar );
varName( $baz );
?>
// Returns
Array
(
[0] => $foo
[1] => foo
)
Array
(
[0] => $bar
[1] => bar
)
Array
(
[0] => $baz
[1] => baz
)
It works based on the line that called the function, where it finds the argument you passed in. I suppose it could be expanded to work with multiple arguments but, like others have said, if you could explain the situation better, another solution would probably work better.
You could use get_defined_vars() to find the name of a variable that has the same value as the one you're trying to find the name of. Obviously this will not always work, since different variables often have the same values, but it's the only way I can think of to do this.
Edit: get_defined_vars() doesn't seem to be working correctly, it returns 'var' because $var is used in the function itself. $GLOBALS seems to work so I've changed it to that.
function print_var_name($var) {
foreach($GLOBALS as $var_name => $value) {
if ($value === $var) {
return $var_name;
}
}
return false;
}
Edit: to be clear, there is no good way to do this in PHP, which is probably because you shouldn't have to do it. There are probably better ways of doing what you're trying to do.
You might consider changing your approach and using a variable variable name?
$var_name = "FooBar";
$$var_name = "a string";
then you could just
print($var_name);
to get
FooBar
Here's the link to the PHP manual on Variable variables
No-one seems to have mentioned the fundamental reasons why this is a) hard and b) unwise:
A "variable" is just a symbol pointing at something else. In PHP, it internally points to something called a "zval", which can actually be used for multiple variables simultaneously, either because they have the same value (PHP implements something called "copy-on-write" so that $foo = $bar doesn't need to allocate extra memory straight away) or because they have been assigned (or passed to a function) by reference (e.g. $foo =& $bar). So a zval has no name.
When you pass a parameter to a function you are creating a new variable (even if it's a reference). You could pass something anonymous, like "hello", but once inside your function, it's whatever variable you name it as. This is fairly fundamental to code separation: if a function relied on what a variable used to be called, it would be more like a goto than a properly separate function.
Global variables are generally considered a bad idea. A lot of the examples here assume that the variable you want to "reflect" can be found in $GLOBALS, but this will only be true if you've structured your code badly and variables aren't scoped to some function or object.
Variable names are there to help programmers read their code. Renaming variables to better suit their purpose is a very common refactoring practice, and the whole point is that it doesn't make any difference.
Now, I understand the desire for this for debugging (although some of the proposed usages go far beyond that), but as a generalised solution it's not actually as helpful as you might think: if your debug function says your variable is called "$file", that could still be any one of dozens of "$file" variables in your code, or a variable which you have called "$filename" but are passing to a function whose parameter is called "$file".
A far more useful piece of information is where in your code the debug function was called from. Since you can quickly find this in your editor, you can see which variable you were outputting for yourself, and can even pass whole expressions into it in one go (e.g. debug('$foo + $bar = ' . ($foo + $bar))).
For that, you can use this snippet at the top of your debug function:
$backtrace = debug_backtrace();
echo '# Debug function called from ' . $backtrace[0]['file'] . ' at line ' . $backtrace[0]['line'];
This is exactly what you want - its a ready to use "copy and drop in" function that echo the name of a given var:
function print_var_name(){
// read backtrace
$bt = debug_backtrace();
// read file
$file = file($bt[0]['file']);
// select exact print_var_name($varname) line
$src = $file[$bt[0]['line']-1];
// search pattern
$pat = '#(.*)'.__FUNCTION__.' *?\( *?(.*) *?\)(.*)#i';
// extract $varname from match no 2
$var = preg_replace($pat, '$2', $src);
// print to browser
echo '<pre>' . trim($var) . ' = ' . print_r(current(func_get_args()), true) . '</pre>';
}
USAGE: print_var_name($FooBar)
PRINT: FooBar
HINT
Now you can rename the function and it will still work and also use the function several times in one line! Thanks to #Cliffordlife
And I add a nicer output! Thanks to #Blue-Water
Lucas on PHP.net provided a reliable way to check if a variable exists. In his example, he iterates through a copy of the global variable array (or a scoped array) of variables, changes the value to a randomly generated value, and checks for the generated value in the copied array.
function variable_name( &$var, $scope=false, $prefix='UNIQUE', $suffix='VARIABLE' ){
if($scope) {
$vals = $scope;
} else {
$vals = $GLOBALS;
}
$old = $var;
$var = $new = $prefix.rand().$suffix;
$vname = FALSE;
foreach($vals as $key => $val) {
if($val === $new) $vname = $key;
}
$var = $old;
return $vname;
}
Then try:
$a = 'asdf';
$b = 'asdf';
$c = FALSE;
$d = FALSE;
echo variable_name($a); // a
echo variable_name($b); // b
echo variable_name($c); // c
echo variable_name($d); // d
Be sure to check his post on PHP.net: http://php.net/manual/en/language.variables.php
I made an inspection function for debugging reasons. It's like print_r() on steroids, much like Krumo but a little more effective on objects. I wanted to add the var name detection and came out with this, inspired by Nick Presta's post on this page. It detects any expression passed as an argument, not only variable names.
This is only the wrapper function that detects the passed expression.
Works on most of the cases.
It will not work if you call the function more than once in the same line of code.
This works fine:
die(inspect($this->getUser()->hasCredential("delete")));
inspect() is the function that will detect the passed expression.
We get: $this->getUser()->hasCredential("delete")
function inspect($label, $value = "__undefin_e_d__")
{
if($value == "__undefin_e_d__") {
/* The first argument is not the label but the
variable to inspect itself, so we need a label.
Let's try to find out it's name by peeking at
the source code.
*/
/* The reason for using an exotic string like
"__undefin_e_d__" instead of NULL here is that
inspected variables can also be NULL and I want
to inspect them anyway.
*/
$value = $label;
$bt = debug_backtrace();
$src = file($bt[0]["file"]);
$line = $src[ $bt[0]['line'] - 1 ];
// let's match the function call and the last closing bracket
preg_match( "#inspect\((.+)\)#", $line, $match );
/* let's count brackets to see how many of them actually belongs
to the var name
Eg: die(inspect($this->getUser()->hasCredential("delete")));
We want: $this->getUser()->hasCredential("delete")
*/
$max = strlen($match[1]);
$varname = "";
$c = 0;
for($i = 0; $i < $max; $i++){
if( $match[1]{$i} == "(" ) $c++;
elseif( $match[1]{$i} == ")" ) $c--;
if($c < 0) break;
$varname .= $match[1]{$i};
}
$label = $varname;
}
// $label now holds the name of the passed variable ($ included)
// Eg: inspect($hello)
// => $label = "$hello"
// or the whole expression evaluated
// Eg: inspect($this->getUser()->hasCredential("delete"))
// => $label = "$this->getUser()->hasCredential(\"delete\")"
// now the actual function call to the inspector method,
// passing the var name as the label:
// return dInspect::dump($label, $val);
// UPDATE: I commented this line because people got confused about
// the dInspect class, wich has nothing to do with the issue here.
echo("The label is: ".$label);
echo("The value is: ".$value);
}
Here's an example of the inspector function (and my dInspect class) in action:
http://inspect.ip1.cc
Texts are in spanish in that page, but code is concise and really easy to understand.
From php.net
#Alexandre - short solution
<?php
function vname(&$var, $scope=0)
{
$old = $var;
if (($key = array_search($var = 'unique'.rand().'value', !$scope ? $GLOBALS : $scope)) && $var = $old) return $key;
}
?>
#Lucas - usage
<?php
//1. Use of a variable contained in the global scope (default):
$my_global_variable = "My global string.";
echo vname($my_global_variable); // Outputs: my_global_variable
//2. Use of a local variable:
function my_local_func()
{
$my_local_variable = "My local string.";
return vname($my_local_variable, get_defined_vars());
}
echo my_local_func(); // Outputs: my_local_variable
//3. Use of an object property:
class myclass
{
public function __constructor()
{
$this->my_object_property = "My object property string.";
}
}
$obj = new myclass;
echo vname($obj->my_object_property, $obj); // Outputs: my_object_property
?>
Many replies question the usefulness of this. However, getting a reference for a variable can be very useful. Especially in cases with objects and $this. My solution works with objects, and as property defined objects as well:
function getReference(&$var)
{
if(is_object($var))
$var->___uniqid = uniqid();
else
$var = serialize($var);
$name = getReference_traverse($var,$GLOBALS);
if(is_object($var))
unset($var->___uniqid);
else
$var = unserialize($var);
return "\${$name}";
}
function getReference_traverse(&$var,$arr)
{
if($name = array_search($var,$arr,true))
return "{$name}";
foreach($arr as $key=>$value)
if(is_object($value))
if($name = getReference_traverse($var,get_object_vars($value)))
return "{$key}->{$name}";
}
Example for the above:
class A
{
public function whatIs()
{
echo getReference($this);
}
}
$B = 12;
$C = 12;
$D = new A;
echo getReference($B)."<br/>"; //$B
echo getReference($C)."<br/>"; //$C
$D->whatIs(); //$D
Adapted from answers above for many variables, with good performance, just one $GLOBALS scan for many
function compact_assoc(&$v1='__undefined__', &$v2='__undefined__',&$v3='__undefined__',&$v4='__undefined__',&$v5='__undefined__',&$v6='__undefined__',&$v7='__undefined__',&$v8='__undefined__',&$v9='__undefined__',&$v10='__undefined__',&$v11='__undefined__',&$v12='__undefined__',&$v13='__undefined__',&$v14='__undefined__',&$v15='__undefined__',&$v16='__undefined__',&$v17='__undefined__',&$v18='__undefined__',&$v19='__undefined__'
) {
$defined_vars=get_defined_vars();
$result=Array();
$reverse_key=Array();
$original_value=Array();
foreach( $defined_vars as $source_key => $source_value){
if($source_value==='__undefined__') break;
$original_value[$source_key]=$$source_key;
$new_test_value="PREFIX".rand()."SUFIX";
$reverse_key[$new_test_value]=$source_key;
$$source_key=$new_test_value;
}
foreach($GLOBALS as $key => &$value){
if( is_string($value) && isset($reverse_key[$value]) ) {
$result[$key]=&$value;
}
}
foreach( $original_value as $source_key => $original_value){
$$source_key=$original_value;
}
return $result;
}
$a = 'A';
$b = 'B';
$c = '999';
$myArray=Array ('id'=>'id123','name'=>'Foo');
print_r(compact_assoc($a,$b,$c,$myArray) );
//print
Array
(
[a] => A
[b] => B
[c] => 999
[myArray] => Array
(
[id] => id123
[name] => Foo
)
)
If the variable is interchangable, you must have logic somewhere that's determining which variable gets used. All you need to do is put the variable name in $variable within that logic while you're doing everything else.
I think we're all having a hard time understanding what you're needing this for. Sample code or an explanation of what you're actually trying to do might help, but I suspect you're way, way overthinking this.
I actually have a valid use case for this.
I have a function cacheVariable($var) (ok, I have a function cache($key, $value), but I'd like to have a function as mentioned).
The purpose is to do:
$colour = 'blue';
cacheVariable($colour);
...
// another session
...
$myColour = getCachedVariable('colour');
I have tried with
function cacheVariable($variable) {
$key = ${$variable}; // This doesn't help! It only gives 'variable'.
// do some caching using suitable backend such as apc, memcache or ramdisk
}
I have also tried with
function varName(&$var) {
$definedVariables = get_defined_vars();
$copyOfDefinedVariables = array();
foreach ($definedVariables as $variable=>$value) {
$copyOfDefinedVariables[$variable] = $value;
}
$oldVar = $var;
$var = !$var;
$difference = array_diff_assoc($definedVariables, $copyOfDefinedVariables);
$var = $oldVar;
return key(array_slice($difference, 0, 1, true));
}
But this fails as well... :(
Sure, I could continue to do cache('colour', $colour), but I'm lazy, you know... ;)
So, what I want is a function that gets the ORIGINAL name of a variable, as it was passed to a function. Inside the function there is no way I'm able to know that, as it seems. Passing get_defined_vars() by reference in the second example above helped me (Thanks to Jean-Jacques Guegan for that idea) somewhat. The latter function started working, but it still only kept returning the local variable ('variable', not 'colour').
I haven't tried yet to use get_func_args() and get_func_arg(), ${}-constructs and key() combined, but I presume it will fail as well.
I have this:
debug_echo(array('$query'=>$query, '$nrUsers'=>$nrUsers, '$hdr'=>$hdr));
I would prefer this:
debug_echo($query, $nrUsers, $hdr);
The existing function displays a yellow box with a red outline and shows each variable by name and value. The array solution works but is a little convoluted to type when it is needed.
That's my use case and yes, it does have to do with debugging. I agree with those who question its use otherwise.
Here's my solution based on Jeremy Ruten
class DebugHelper {
function printVarNames($systemDefinedVars, $varNames) {
foreach ($systemDefinedVars as $var=>$value) {
if (in_array($var, $varNames )) {
var_dump($var);
var_dump($value);
}
}
}
}
using it
DebugHelper::printVarNames(
$systemDefinedVars = get_defined_vars(),
$varNames=array('yourVar00', 'yourVar01')
);
You could use compact() to achieve this.
$FooBar = "a string";
$newArray = compact('FooBar');
This would create an associative array with the variable name as the key. You could then loop through the array using the key name where you needed it.
foreach($newarray as $key => $value) {
echo $key;
}
I think you want to know variable name with it's value. You can use an associative array to achieve this.
use variable names for array keys:
$vars = array('FooBar' => 'a string');
When you want to get variable names, use array_keys($vars), it will return an array of those variable names that used in your $vars array as it's keys.
This is the way I did it
function getVar(&$var) {
$tmp = $var; // store the variable value
$var = '_$_%&33xc$%^*7_r4'; // give the variable a new unique value
$name = array_search($var, $GLOBALS); // search $GLOBALS for that unique value and return the key(variable)
$var = $tmp; // restore the variable old value
return $name;
}
Usage
$city = "San Francisco";
echo getVar($city); // city
Note: some PHP 7 versions will not work properly due to a bug in array_search with $GLOBALS, however all other versions will work.
See this https://3v4l.org/UMW7V
There is no predefined function in PHP that can output the name of a variable. However, you can use the result of get_defined_vars(), which returns all the variables defined in the scope, including name and value. Here is an example:
<?php
// Function for determining the name of a variable
function getVarName(&$var, $definedVars=null) {
$definedVars = (!is_array($definedVars) ? $GLOBALS : $definedVars);
$val = $var;
$rand = 1;
while (in_array($rand, $definedVars, true)) {
$rand = md5(mt_rand(10000, 1000000));
}
$var = $rand;
foreach ($definedVars as $dvName=>$dvVal) {
if ($dvVal === $rand) {
$var = $val;
return $dvName;
}
}
return null;
}
// the name of $a is to be determined.
$a = 1;
// Determine the name of $a
echo getVarName($a);
?>
Read more in How to get a variable name as a string in PHP?
Why don't you just build a simple function and TELL it?
/**
* Prints out $obj for debug
*
* #param any_type $obj
* #param (string) $title
*/
function print_all( $obj, $title = false )
{
print "\n<div style=\"font-family:Arial;\">\n";
if( $title ) print "<div style=\"background-color:red; color:white; font-size:16px; font-weight:bold; margin:0; padding:10px; text-align:center;\">$title</div>\n";
print "<pre style=\"background-color:yellow; border:2px solid red; color:black; margin:0; padding:10px;\">\n\n";
var_export( $obj );
print "\n\n</pre>\n</div>\n";
}
print_all( $aUser, '$aUser' );
I was looking for this but just decided to pass the name in, I usually have the name in the clipboard anyway.
function VarTest($my_var,$my_var_name){
echo '$'.$my_var_name.': '.$my_var.'<br />';
}
$fruit='apple';
VarTest($fruit,'fruit');
I know this is old and already answered but I was actually looking for this. I am posting this answer to save people a little time refining some of the answers.
Option 1:
$data = array('$FooBar');
$vars = [];
$vars = preg_replace('/^\\$/', '', $data);
$varname = key(compact($vars));
echo $varname;
Prints:
FooBar
For whatever reason you would find yourself in a situation like this, it does actually work.
.
Option 2:
$FooBar = "a string";
$varname = trim(array_search($FooBar, $GLOBALS), " \t.");
echo $varname;
If $FooBar holds a unique value, it will print 'FooBar'. If $FooBar is empty or null it will print the name of the first empty or null string it finds.
It could be used as such:
if (isset($FooBar) && !is_null($FooBar) && !empty($FooBar)) {
$FooBar = "a string";
$varname = trim(array_search($FooBar, $GLOBALS), " \t.");
}
other use:
shrug
function varsToArrayAssoc(...$arguments){
$bt = debug_backtrace();
$file = file($bt[0]['file']);
$src = $file[$bt[0]['line']-1];
$pat = '#(.*)'.__FUNCTION__.' *?\( *?(.*) *?\)(.*)#i';
$vars =explode(',',substr_replace(trim(preg_replace($pat, '$2', $src)) ,"", -1));
$result=[];
foreach(func_get_args() as $key=>$v){
$index=trim(explode('$',$vars[$key])[1]);
$result[$index]=$v;
}
return $result;
}
$a=12;
$b=13;
$c=123;
$d='aa';
var_dump(varsToArrayAssoc($a,$b,$c,$d));
Use this to detach user variables from global to check variable at the moment.
function get_user_var_defined ()
{
return array_slice($GLOBALS,8,count($GLOBALS)-8);
}
function get_var_name ($var)
{
$vuser = get_user_var_defined();
foreach($vuser as $key=>$value)
{
if($var===$value) return $key ;
}
}
It may be considered quick and dirty, but my own personal preference is to use a function/method like this:
public function getVarName($var) {
$tmp = array($var => '');
$keys = array_keys($tmp);
return trim($keys[0]);
}
basically it just creates an associative array containing one null/empty element, using as a key the variable for which you want the name.
we then get the value of that key using array_keys and return it.
obviously this gets messy quick and wouldn't be desirable in a production environment, but it works for the problem presented.
why we have to use globals to get variable name... we can use simply like below.
$variableName = "ajaxmint";
echo getVarName('$variableName');
function getVarName($name) {
return str_replace('$','',$name);
}
I really fail to see the use case... If you will type print_var_name($foobar) what's so hard (and different) about typing print("foobar") instead?
Because even if you were to use this in a function, you'd get the local name of the variable...
In any case, here's the reflection manual in case there's something you need in there.

Categories