Как получить имя переменной в виде строки в PHP?

Скажем, у меня есть этот код PHP:

$FooBar = "a string";

тогда мне нужна такая функция:

print_var_name($FooBar);

который печатает:

FooBar

Есть идеи как этого добиться? Это вообще возможно в PHP?

180

Решение

Вы могли бы использовать get_defined_vars () чтобы найти имя переменной, значение которой совпадает со значением, которое вы пытаетесь найти. Очевидно, это не всегда будет работать, поскольку разные переменные часто имеют одинаковые значения, но это единственный способ, которым я могу придумать.

Edit: get_defined_vars (), кажется, не работает правильно, он возвращает ‘var’, потому что $ var используется в самой функции. $ GLOBALS, кажется, работает, поэтому я изменил его на это.

function print_var_name($var) {
foreach($GLOBALS as $var_name => $value) {
if ($value === $var) {
return $var_name;
}
}

return false;
}

Изменить: чтобы было ясно, нет хорошего способа сделать это в PHP, что, вероятно, потому, что вам не нужно это делать. Вероятно, есть лучшие способы сделать то, что вы пытаетесь сделать.

36

Другие решения

Я не мог придумать способ сделать это эффективно, но я придумал это. Это работает, для ограниченного использования ниже.

пожимание плечами

<?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
)

Он работает на основе строки, вызвавшей функцию, где находит аргумент, который вы передали. Я полагаю, что его можно расширить для работы с несколькими аргументами, но, как говорили другие, если бы вы могли объяснить ситуацию лучше, возможно, было бы другое решение. работать лучше

42

Вы могли бы подумать об изменении вашего подхода и использовании имени переменной переменной?

$var_name = "FooBar";
$$var_name = "a string";

тогда вы могли бы просто

print($var_name);

получить

FooBar

Вот ссылка на Руководство по PHP для переменных переменных

25

Никто, кажется, не упомянул фундаментальные причины Зачем это а) сложно и б) неразумно

  • «Переменная» — это просто символ, указывающий на что-то еще. В PHP он внутренне указывает на то, что называется «zval», который может фактически использоваться для нескольких переменных одновременно, либо потому, что они имеют одно и то же значение (PHP реализует нечто, называемое «копирование при записи», так что $foo = $bar не нужно сразу выделять дополнительную память) или потому, что они были назначены (или переданы функции) по ссылке (например, $foo =& $bar). Так что у звала нет имени.
  • Когда вы передаете параметр в функцию, вы создаете новый переменная (даже если это ссылка). Вы можете передать что-то анонимное, как "hello", но когда-то внутри вашей функции, это любая переменная, которую вы называете. Это довольно фундаментально для разделения кода: если функция полагается на переменную используемый чтобы быть названным, это было бы больше похоже на goto чем правильно отдельная функция.
  • Глобальные переменные обычно считаются плохой идеей. Многие примеры здесь предполагают, что переменная, которую вы хотите «отразить», находится в $GLOBALS, но это будет верно только в том случае, если вы плохо структурировали свой код и переменные не ограничены какой-либо функцией или объектом.
  • Имена переменных помогают программистам читать их код. Переименование переменных для лучшего соответствия их назначению — очень распространенная практика рефакторинга, и весь смысл в том, что это не имеет никакого значения.

Теперь я понимаю желание этого для отладки (хотя некоторые из предложенных вариантов использования выходят далеко за рамки этого), но в качестве обобщенного решения это на самом деле не так полезно, как вы думаете: если ваша функция отладки говорит, что ваша переменная называется «$ file «, это может быть любая из десятков переменных» $ file «в вашем коде или переменная, которую вы назвали» $ filename «, но передаете функции, параметр которой называется» $ file «.

Гораздо более полезная информация — это то, откуда в вашем коде была вызвана функция отладки. Поскольку вы можете быстро найти это в своем редакторе, вы можете увидеть, какую переменную вы выводили для себя, и даже можете передать целые выражения в нее за один раз (например, debug('$foo + $bar = ' . ($foo + $bar))).

Для этого вы можете использовать этот фрагмент вверху функции отладки:

$backtrace = debug_backtrace();
echo '# Debug function called from ' . $backtrace[0]['file'] . ' at line ' . $backtrace[0]['line'];
18

Я сделал функцию проверки по причинам отладки. Это похоже на print_r () на стероидах, очень похоже на Krumo, но немного более эффективно на объектах. Я хотел добавить определение имени var и получил это, вдохновленный постом Ника Престы на этой странице. Он обнаруживает любое выражение, переданное в качестве аргумента, а не только имена переменных.

Это только функция-обертка, которая обнаруживает переданное выражение.
Работает в большинстве случаев.
Это не будет работать, если вы вызываете функцию более одного раза в одной и той же строке кода.

Это отлично работает:
умереть(осмотреть($ This-> GetUser () -> hasCredential ( «Удалить»)));

inspect () — это функция, которая обнаружит переданное выражение.

Мы получаем: $ This-> GetUser () -> hasCredential ( «Удалить»)

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);

}

Вот пример функции инспектора (и моего класса dInspect) в действии:

http://inspect.ip1.cc

Тексты на этой странице на испанском, но код лаконичен и действительно прост для понимания.

13

Lucas на PHP.net предоставил надежный способ проверить, существует ли переменная. В своем примере он перебирает копию массива глобальных переменных (или массива с областями видимости) переменных, изменяет значение на случайно сгенерированное значение и проверяет сгенерированное значение в скопированном массиве.

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;
}

Тогда попробуйте:

$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

Обязательно проверьте его пост на PHP.net: http://php.net/manual/en/language.variables.php

9

От php.net

@Alexandre — короткое решение

<?php
function vname(&$var, $scope=0)
{
$old = $var;
if (($key = array_search($var = 'unique'.rand().'value', !$scope ? $GLOBALS : $scope)) && $var = $old) return $key;
}
?>

@Lucas — использование

<?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
?>
5

Это именно то, что вы хотите — это готовая к использованию функция «копировать и вставить», которая отображает имя данной переменной:

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 trim($var);
}

ИСПОЛЬЗОВАНИЕ: print_var_name ($ FooBar)

ПЕЧАТЬ: FooBar

ПОДСКАЗКА
Теперь вы можете переименовать функцию, и она все равно будет работать, а также использовать функцию несколько раз в одной строке! Благодаря @Cliffordlife

5
По вопросам рекламы [email protected]