Storing and accessing a snippet of code in a function - php

In my includes folder I have a function...
function storelistingUno() {
$itemnum=mysql_real_escape_string($_POST['itemnum']);
$msrp=mysql_real_escape_string($_POST['msrp']);
$edprice=mysql_real_escape_string($_POST['edprice']); //This value has to be the same as in the HTML form file
$itemtype=mysql_real_escape_string($_POST['itemtype']);
$box=mysql_real_escape_string($_POST['box']);
$box2=mysql_real_escape_string($_POST['box2']);
$box25=mysql_real_escape_string($_POST['box25']);
$box3=mysql_real_escape_string($_POST['box3']);
$box4=mysql_real_escape_string($_POST['box4']);
$box5=mysql_real_escape_string($_POST['box5']);
$box6=mysql_real_escape_string($_POST['box6']);
$box7=mysql_real_escape_string($_POST['box7']);
$box8=mysql_real_escape_string($_POST['box8']);
$itemcolor=mysql_real_escape_string($_POST['itemcolor']);
$link=mysql_real_escape_string($_POST['link']);
$test = "yes!";
}
I reference this in about 8 pages and I decided it would be easier to just make a function out of it and only touch this from now on. So I referenced storelistingUno(); in my code, but I don't think it worked, because I tried to execute echo $test; and nothing happened. Do I need to return something?
Thanks.

Look into extract(). You can do something like this:
<?php
function getEscapedArray()
{
$keys = array('itemnum', 'msrp', 'edprice', 'itemtype', 'box', 'box2', 'box25', 'box3', 'box4', 'box5', 'box6', 'box7', 'box8', 'itemcolor', 'link');
$returnValues = array();
foreach ($keys as $key) {
$returnValues[$key] = mysql_real_escape_string($_POST[$key]);
}
$returnValues['test'] = 'yes!';
return $returnValues;
}
extract(getEscapedArray());
echo $test;
Although - Its still not the best way to do this. The best would be to just use the return from that function as the array.
$parsedVals = getEscapedArray();
echo $parsedVals["test"];

If you absolutely need these variables a globals
function storelistingUno()
{
$desiredGlobals = array(
'itemnum'
,'msrp'
,'edprice'
,'itemtype'
,'box'
,'box2'
,'box25'
,'box3'
,'box4'
,'box5'
,'box6'
,'box7'
,'box8'
,'itemcolor'
,'link'
);
foreach ( $desiredGlobals as $globalName )
{
if ( isset( $_POST[$globalName] ) )
{
$GLOBALS[$globalName] = mysql_real_escape_string( $_POST[$globalName] );
}
}
}

$test is a local variable in that function - you either need to make it global (by putting global $test; at the start of the function or using $GLOBALS['test'] instead of just $test or return the value.
Are you thinking of using that function to just escape the values? Maybe you could make it perform the query too, then you wouldn't have to return / use globals.
Edit:
A different way would be to include the code instead of using a function - not recommended though...

You would have to mark every variable as global before you start to edit them within the function ... this isn't recommented since it's bad coding style but it might help you
$test = '';
function foo() {
global $test;
$test = 'bar';
}
echo $test; //prints nothing
foo();
echo $test; // prints "bar"

Related

Access a global variable in a PHP function

According to the most programming languages scope rules, I can access variables that are defined outside of functions inside them, but why doesn't this code work?
<?php
$data = 'My data';
function menugen() {
echo "[" . $data . "]";
}
menugen();
?>
The output is [].
To address the question as asked, it is not working because you need to declare which global variables you'll be accessing in the function itself:
$data = 'My data';
function menugen() {
global $data; // <-- Add this line
echo "[" . $data . "]";
}
menugen();
Otherwise you can access it as $GLOBALS['data'], see Variable scope.
Even if a little off-topic, I would suggest you avoid using globals at all and prefer passing data as parameters.
In this case, the above code look like this:
$data = 'My data';
function menugen($data) { // <-- Declare the parameter
echo "[" . $data . "]";
}
menugen($data); // <-- And pass it at call time
You can do one of the following:
<?php
$data = 'My data';
function menugen() {
global $data;
echo "[" . $data . "]";
}
menugen();
Or
<?php
$data = 'My data';
function menugen() {
echo "[" . $GLOBALS['data'] . "]";
}
menugen();
That being said, overuse of globals can lead to some poor code. It is usually better to pass in what you need. For example, instead of referencing a global database object you should pass in a handle to the database and act upon that. This is called dependency injection. It makes your life a lot easier when you implement automated testing (which you should).
Another way to do it:
<?php
$data = 'My data';
$menugen = function() use ($data) {
echo "[".$data."]";
};
$menugen();
UPDATE 2020-01-13: requested by Peter Mortensen
As of PHP 5.3.0 we have anonymous functions support that can create closures. A closure can access the variable which is created outside of its scope.
In the example, the closure is able to access $data because it was declared in the use clause.
It's a matter of scope. In short, global variables should be avoided so:
You either need to pass it as a parameter:
$data = 'My data';
function menugen($data)
{
echo $data;
}
Or have it in a class and access it
class MyClass
{
private $data = "";
function menugen()
{
echo this->data;
}
}
See #MatteoTassinari answer as well, as you can mark it as global to access it, but global variables are generally not required, so it would be wise to re-think your coding.
For many years I have always used this format:
<?php
$data = "Hello";
function sayHello(){
echo $GLOBALS["data"];
}
sayHello();
?>
I find it straightforward and easy to follow. The $GLOBALS is how PHP lets you reference a global variable. If you have used things like $_SERVER, $_POST, etc. then you have reference a global variable without knowing it.
I was looking for this answer, sort of, I wanted to see if anyone else had something similar with respect to how $prefix would be passed to an anonymous function. Seems the global scope is the the way? This is my solution for prefixing an array in a non-destructive manner.
private function array_prefix($prefix, $arr) {
$GLOBALS['prefix'] = $prefix;
return array_map(
function($ele) {
return $GLOBALS['prefix'].$ele;
},
$arr
);
}
<?php
$data = 'My data';
$menugen = function() use ($data) {
echo "[ $data ]";
};
$menugen();
?>
You can also simplify
echo "[" . $data . "]"
to
echo "[$data]"
PHP can be frustrating for this reason. The answers above using global did not work for me, and it took me awhile to figure out the proper use of use.
This is correct:
$functionName = function($stuff) use ($globalVar) {
//do stuff
}
$output = $functionName($stuff);
$otherOutput = $functionName($otherStuff);
This is incorrect:
function functionName($stuff) use ($globalVar) {
//do stuff
}
$output = functionName($stuff);
$otherOutput = functionName($otherStuff);
Using your specific example:
$data = 'My data';
$menugen = function() use ($data) {
echo "[" . $data . "]";
}
$menugen();
The proper way for accessing a global variable inside a function is answered above!
BUT if you do not want to use the global keyword, nor the $GLOBALS variable for some reason (for example you have multiple functions and you are "tired" of writing global $variable; every time), here is a workaround:
$variable = 42; // the global variable you want to access
// write a function which returns it
function getvar(){
global $variable;
return $variable;
}
//--------------
function func1()
{
// use that getter function to get the global variable
echo getvar(); // 42
}
function func2()
{
echo getvar(); // 42
}
...
You need to pass the variable into the function:
$data = 'My data';
function menugen($data)
{
echo $data;
}

PHP global declaration

I'm using PHP's global declaration to make an array available to a number of functions in a script. The variable is declared at the top of the script and is referenced with global in each of the functions which uses it, as follows:
<?php
$myarray = array(1, 2, 3);
function print_my_array() {
global $myarray;
print '<ul>';
foreach($myarray as $entry) {
print '<li>'.$entry.'</li>';
}
print '</ul>';
return 0;
}
print_my_array();
?>
Sometimes, but not always, the array is not set when the function is called, generating an error when the foreach is called. In the actual code, the array used is given a very unique name and so should not be causing any collisions with anything else. Am I mis-using the global declaration?
No, the snippet is correct. The problem you're having is the problem of using global variables – they can be accessed and changed from anywhere (perhaps accidental), thereby creating hard-to-find bugs.
By using globals you can hit quite a few gotchas, they'll also make you code less reusable.
Here's an example of your function which can be re-used many times across the site.
(untested)
<?php
function arrayTags($items, $open = '<li>', $close = '</li>')
{
if (is_array($items) && count($items) != 0)
{
$output = null;
foreach ($items as $item) {
$output .= $open . $item . $close;
}
return $output;
}
else
{
return '';
}
}
// Default, <li>
echo '<ul>' . arrayTags($myarray) . '</ul>';
// or, spans:
echo '<div id="container">' . arrayTags($myarray, '<span>', '</span>') . '</div>';
The least you could do is check if the array is null at the top of the function, before you run the foreach. that would at least prevent the error:
function print_my_array() {
global $myarray;
if(!empty($myarray)) {
print '<ul>';
foreach($myarray as $entry) {
print '<li>'.$entry.'</li>';
}
print '</ul>';
}
}
Also, I wouldn't just return 0 for the hell of it. You may want to incorporate whether or not the array was empty into what you return from this function.
$myarray = array(1, 2, 3);
In short you have to only declare it like so:
$myarray = array();
and if you want to populate it with values do that in the class constructor:
public function __construct(){
$myarray = array(1,2,3);
}
I'm no guru, but in my experience it seems that php doesn't like to execute function calls outside of a function within a class.
THIS DOES NOT WORK:
class MyClass {
public $mystring = myfunction();
public function myFunction(){
return true; //and your function code
}
}
so when you use array() it doesn't actually trigger any function call, it just creats an empty variable of type array. when you use array(1,2,3), it has to effectively run the 'create array' which is like a function.
I know annoying, I'd like it to be different, but I don't know a way of doing what you want in php. Let me know if there is a nice way I'd love to hear it!

PHP call_user_func vs. just calling function

I'm sure there's a very easy explanation for this. What is the difference between this:
function barber($type){
echo "You wanted a $type haircut, no problem\n";
}
call_user_func('barber', "mushroom");
call_user_func('barber', "shave");
... and this (and what are the benefits?):
function barber($type){
echo "You wanted a $type haircut, no problem\n";
}
barber('mushroom');
barber('shave');
Always use the actual function name when you know it.
call_user_func is for calling functions whose name you don't know ahead of time but it is much less efficient since the program has to lookup the function at runtime.
Although you can call variable function names this way:
function printIt($str) { print($str); }
$funcname = 'printIt';
$funcname('Hello world!');
there are cases where you don't know how many arguments you're passing. Consider the following:
function someFunc() {
$args = func_get_args();
// do something
}
call_user_func_array('someFunc',array('one','two','three'));
It's also handy for calling static and object methods, respectively:
call_user_func(array('someClass','someFunc'),$arg);
call_user_func(array($myObj,'someFunc'),$arg);
the call_user_func option is there so you can do things like:
$dynamicFunctionName = "barber";
call_user_func($dynamicFunctionName, 'mushroom');
where the dynamicFunctionName string could be more exciting and generated at run-time. You shouldn't use call_user_func unless you have to, because it is slower.
With PHP 7 you can use the nicer variable-function syntax everywhere. It works with static/instance functions, and it can take an array of parameters. More info at https://trowski.com/2015/06/20/php-callable-paradox
$ret = $callable(...$params);
I imagine it is useful for calling a function that you don't know the name of in advance...
Something like:
switch($value):
{
case 7:
$func = 'run';
break;
default:
$func = 'stop';
break;
}
call_user_func($func, 'stuff');
There are no benefits to call it like that, the word user mean it is for multiple user, it is useful to create modification without editing in core engine.
it used by wordpress to call user function in plugins
<?php
/* main.php */
require("core.php");
require("my_plugin.php");
the_content(); // "Hello I live in Tasikmalaya"
...
<?php
/* core.php */
$listFunc = array();
$content = "Hello I live in ###";
function add_filter($fName, $funct)
{
global $listFunc;
$listFunc[$fName] = $funct;
}
function apply_filter($funct, $content)
{
global $listFunc;
foreach ($listFunc as $key => $value)
{
if ($key == $funct and is_callable($listFunc[$key]))
{
$content = call_user_func($listFunc[$key], $content);
}
}
echo $content;
}
function the_content()
{
global $content;
$content = apply_filter('the_content', $content);
echo $content;
}
....
<?php
/* my_plugin.php */
function changeMyLocation($content){
return str_replace('###', 'Tasikmalaya', $content);
}
add_filter('the_content', 'changeMyLocation');
in your first example you're using function name which is a string. it might come from outside or be determined on the fly. that is, you don't know what function will need to be run at the moment of the code creation.
When using namespaces, call_user_func() is the only way to run a function you don't know the name of beforehand, for example:
$function = '\Utilities\SearchTools::getCurrency';
call_user_func($function,'USA');
If all your functions were in the same namespace, then it wouldn't be such an issue, as you could use something like this:
$function = 'getCurrency';
$function('USA');
Edit:
Following #Jannis saying that I'm wrong I did a little more testing, and wasn't having much luck:
<?php
namespace Foo {
class Bar {
public static function getBar() {
return 'Bar';
}
}
echo "<h1>Bar: ".\Foo\Bar::getBar()."</h1>";
// outputs 'Bar: Bar'
$function = '\Foo\Bar::getBar';
echo "<h1>Bar: ".$function()."</h1>";
// outputs 'Fatal error: Call to undefined function \Foo\Bar::getBar()'
$function = '\Foo\Bar\getBar';
echo "<h1>Bar: ".$function()."</h1>";
// outputs 'Fatal error: Call to undefined function \foo\Bar\getBar()'
}
You can see the output results here: https://3v4l.org/iBERh it seems the second method works for PHP 7 onwards, but not PHP 5.6.

PHP static variables in double quotes

How can I get PHP to evaluate a static variable in double quotes?
I want to do something like this:
log("self::$CLASS $METHOD entering");
I've tried all sorts of {} combos to get the variable value of self::$CLASS, but nothing has worked. I've currently settled with string concatenation but it is a pain to type:
log(self::$CLASS . " $METHOD entering");
Sorry, you can't do that. It only works for simple expressions. See here.
Unfortunately there is no way how to do this yet. Example in one of answers here will not work, because {${self::$CLASS}} will not returns content of self::$CLASS, but will returns content of variable with name in self::$CLASS.
Here is an example, which does not returns myvar, but aaa:
$myvar = 'aaa';
self::$CLASS = 'myvar';
echo "{${self::$CLASS}}";
Use an anonymous identity function stored in a variable. This way you will have $ immediately after {:
$I = function($v) { return $v; };
$interpolated = "Doing {$I(self::FOO)} with {$I(self::BAR)}";
(I am using class constants in this example but this will work with static variables too).
I don’t know the answer to your question, but you can show the class name and method using the __METHOD__ magic constant.
<?php
class test {
public $static = 'text';
public $self = __CLASS__;
// static Method
static function author() {
return "Frank Glück";
}
// static variable
static $url = 'https://www.dozent.net';
public function dothis() {
$self = __CLASS__;
echo <<<TEST
{${!${''}=static::author()}} // works
{$self::author()} // works
{$this->self::author()} // works
${!${''}=self::author()} // works
{${$this->self}}::author()}} // don't works
${${self::author()}} // do/don't works but with notice
${#${self::author()}} // works but with # !
TEST;
}
}
$test = 'test'; // this is the trick, put the Classname into a variable
echo "{$test::author()} {$$test::$url}";
echo <<<HTML
<div>{$test::author()}</div>
<div>{$$test::$url}</div>
HTML;
$test = new test();
$test->dothis();
I know this is an old question but I find it odd that noone has suggested the [sprintf][1] function yet.
say:
<?php
class Foo {
public static $a = 'apple';
}
you would use it with:
echo sprintf( '$a value is %s', Foo::$a );
so on your example its:
log(
sprintf ( ' %s $METHOD entering', self::$CLASS )
);
//define below
function EXPR($v) { return $v; }
$E = EXPR;
//now you can use it in string
echo "hello - three is equal to $E(1+2)";
Just live with the concatenation. You'd be surprised how inefficient variable interpolation in strings can be.
And while this could fall under the umbrella of pre-optimization or micro-optimization, I just don't think you actually gain any elegance in this example.
Personally, if I'm gonna make a tiny optimization of one or the other, and my choices are "faster" and "easier to type" - I'm gonna choose "faster". Because you only type it a few times, but it's probably going to execute thousands of times.
Yes this can be done:
log("{${self::$CLASS}} $METHOD entering");

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