このPHPコードがあるとしましょう:
$FooBar = "a string";
次に、次のような関数が必要です。
print_var_name($FooBar);
印刷する:
FooBar
これを達成する方法はありますか?これはPHPでも可能ですか?
rootName => modelObject
配列内にラップする必要があるだけで、応答に不必要な深さが追加されます。これが言語のランタイムリフレクション機能に組み込まれているといいのですが。
このPHPコードがあるとしましょう:
$FooBar = "a string";
次に、次のような関数が必要です。
print_var_name($FooBar);
印刷する:
FooBar
これを達成する方法はありますか?これはPHPでも可能ですか?
rootName => modelObject
配列内にラップする必要があるだけで、応答に不必要な深さが追加されます。これが言語のランタイムリフレクション機能に組み込まれているといいのですが。
回答:
get_defined_vars()を使用して、名前を見つけようとしている変数と同じ値を持つ変数の名前を見つけることができます。異なる変数が同じ値を持っていることが多いため、これが常に機能するとは限りませんが、これが私がこれを行うために考え得る唯一の方法です。
編集: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でこれを実行する良い方法はありません。これはおそらく、実行する必要がないためです。あなたがやろうとしていることを行うには、おそらくもっと良い方法があるでしょう。
これを効率的に行う方法も考えられませんでしたが、これを思いつきました。以下の限られた用途で機能します。
肩をすくめる
<?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
)
関数を呼び出した行に基づいて機能し、渡された引数を見つけます。複数の引数で機能するように拡張できると思いますが、他の人が言ったように、状況をよりよく説明できれば、別の解決策はおそらくよりよく働く。
アプローチを変更し、変数名を使用することを検討しますか?
$var_name = "FooBar";
$$var_name = "a string";
それならあなたはただ
print($var_name);
取得するため
FooBar
$FooBar
値で変数を実際に作成しますa string
。これは恐ろしい私見です。変数$FooBar
に値を割り当てることはありませんが、値は存在します。OUCH
これがa)難しい、b)賢くないという根本的な理由について誰も言及していないようです:
$foo = $bar
には必要ありません。すぐに追加のメモリを割り当てる)、または参照によって割り当てられている(または関数に渡されている)ため(例:)$foo =& $bar
。したがって、zvalには名前がありません。"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'];
これはまさにあなたが望むものです-それは与えられた変数の名前をエコーするすぐに使える「コピーとドロップイン」機能です:
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
ヒント これで、関数の名前を変更できます。関数は引き続き機能し、関数を1行で数回使用することもできます。@Cliffordlifeに感謝
$pat = '#(.*)'.__FUNCTION__.' *?\( *?(.*) *?\)(.*)#i';
このように少し変更して、このデバッグ関数が何と呼ばれるかは気にせず、関数に渡されるもの、つまり$ helloまたは "hello"を正確に取得します(渡された変数の$一致を削除しました同じ行で)
print_var_name, echo, var_dump
ます$variable); echo ' '; var_dump($variable
PHP.netのLucasは、変数が存在するかどうかを確認する信頼できる方法を提供しました。彼の例では、変数のグローバル変数配列(またはスコープ配列)のコピーを反復処理し、値をランダムに生成された値に変更し、コピーされた配列で生成された値を確認します。
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
break;
、foreach +で等しいことがわかったときだけです。関数内で定義されている場合でも、var_nameを自動的に取得するための使用可能な基本構造を作成しました。コピー&ペーストを頻繁に行っている場合、またはそれを改善するためのより良いアイデアがある場合は、variable_name( $variable, ( empty(__FUNCTION__) ? false : get_defined_vars() ) );
デバッグのために検査機能を作りました。これはステロイドのprint_r()に似ていますが、Krumoによく似ていますが、オブジェクトに対しては少し効果的です。私はvar名の検出を追加したかったので、このページへのNick Prestaの投稿に触発されてこれを思いつきました。変数名だけでなく、引数として渡された式を検出します。
これは、渡された式を検出するラッパー関数のみです。ほとんどの場合で機能します。同じコード行で関数を複数回呼び出す場合は機能しません。
これは正常に動作します:die(inspect($ this-> getUser()-> hasCredential( "delete")));
inspect()は、渡された式を検出する関数です。
$ 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);
}
以下は、実行中のインスペクター関数(および私のdInspectクラス)の例です。
そのページのテキストはスペイン語ですが、コードは簡潔で本当に理解しやすいです。
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
?>
多くの回答がこれの有用性を疑問視しています。ただし、変数の参照を取得すると非常に便利です。特にオブジェクトと$ thisの場合。私のソリューションはオブジェクトで動作し、プロパティ定義オブジェクトとしても動作します:
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}";
}
上記の例:
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
上記の回答から多くの変数に適応し、優れたパフォーマンスで、1つの$ GLOBALSスキャンで多くの
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
)
)
私は実際にこれの有効なユースケースを持っています。
私は関数cacheVariable($ var)を持っています(わかりました、関数cache($ key、$ value)を持っていますが、前述のように関数が欲しいです)。
目的は次のとおりです。
$colour = 'blue';
cacheVariable($colour);
...
// another session
...
$myColour = getCachedVariable('colour');
私は試しました
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
}
私も試しました
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));
}
しかし、これも失敗します... :(
確かに、私はcache( 'colour'、$ colour)を続けることができますが、私は怠惰です、あなたは知っています...;)
したがって、関数に渡されたときに、変数の元の名前を取得する関数が必要です。関数内では、どうやらそれを知る方法はありません。上記の2番目の例で参照によりget_defined_vars()を渡すことは、私にいくらか役立ちました(そのアイデアについてJean-Jacques Gueganに感謝します)。後者の関数は機能し始めましたが、ローカル変数( '変数'ではなく '色')を返すだけでした。
get_func_args()とget_func_arg()、$ {}-constructs、key()を組み合わせて使用することはまだ試みていませんが、同様に失敗すると思います。
cacheVariable(compact('color'))
私はこれを持っています:
debug_echo(array('$query'=>$query, '$nrUsers'=>$nrUsers, '$hdr'=>$hdr));
私はこれを好みます:
debug_echo($query, $nrUsers, $hdr);
既存の関数は、赤い枠の付いた黄色のボックスを表示し、各変数を名前と値で示します。配列ソリューションは機能しますが、必要なときにタイプするのは少し複雑です。
それは私のユースケースであり、はい、デバッグに関係しています。私はそれ以外の場合の使用に疑問を抱く人々に同意します。
これはに基づいて私の解決策です Jeremy Ruten
class DebugHelper {
function printVarNames($systemDefinedVars, $varNames) {
foreach ($systemDefinedVars as $var=>$value) {
if (in_array($var, $varNames )) {
var_dump($var);
var_dump($value);
}
}
}
}
それを使う
DebugHelper::printVarNames(
$systemDefinedVars = get_defined_vars(),
$varNames=array('yourVar00', 'yourVar01')
);
単純な関数を作成して教えてみませんか?
/**
* 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' );
変数名とその値を知りたいと思います。これを行うには、連想配列を使用できます。
配列キーには変数名を使用します。
$vars = array('FooBar' => 'a string');
変数名を取得するには、を使用しますarray_keys($vars)
。これは、配列で$vars
キーとして使用されている変数名の配列を返します。
これは古く、すでに回答済みですが、実際に探していました。私はこの回答を投稿して、回答の一部を改善する時間を少し節約できるようにしています。
オプション1:
$data = array('$FooBar');
$vars = [];
$vars = preg_replace('/^\\$/', '', $data);
$varname = key(compact($vars));
echo $varname;
プリント:
FooBar
どんな理由であれ、あなたはこのような状況にいることに気づくでしょう、それは実際に機能します。
。
オプション2:
$FooBar = "a string";
$varname = trim(array_search($FooBar, $GLOBALS), " \t.");
echo $varname;
場合は$FooBar
一意の値を保持し、それはFooBarの"を出力します。$FooBar
空またはnullの場合、最初に見つかった空またはnull文字列の名前を出力します。
次のように使用できます。
if (isset($FooBar) && !is_null($FooBar) && !empty($FooBar)) {
$FooBar = "a string";
$varname = trim(array_search($FooBar, $GLOBALS), " \t.");
}
これは私がやった方法です
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;
}
使用法
$city = "San Francisco";
echo getVar($city); // city
注:一部のPHP 7バージョンは、のバグのために正しく動作しませんarray_search
が$GLOBALS
、他のすべてのバージョンは動作します。
これを参照してくださいhttps://3v4l.org/UMW7V
これを使用して、ユーザー変数をグローバルから切り離し、現時点で変数をチェックします。
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 ;
}
}
print implode( ' ', array_keys( $GLOBALS ));
「デフォルト」グローバルの数に関する誤った仮定のように見えます。私のシステムには7つのスーパーグローバルがあります:$ _GET、$ _ POST、$ _ COOKIE、$ _ FILES、$ _ ENV、$ _ REQUEST、$ _ SERVER。また、argvとargcもあります。したがって、オフセットは9である必要があります。デフォルトではとにかく配列の最後まで実行するだけなので、3番目のパラメーター(長さ)を指定しても意味がありません。
素早いと思われるかもしれませんが、私の個人的な好みは、次のような関数/メソッドを使用することです。
public function getVarName($var) {
$tmp = array($var => '');
$keys = array_keys($tmp);
return trim($keys[0]);
}
基本的には、名前が必要な変数をキーとして使用して、1つのnull /空の要素を含む連想配列を作成するだけです。
次に、array_keysを使用してそのキーの値を取得し、それを返します。
これは明らかに乱雑になり、実稼働環境では望ましくありませんが、提示された問題に対しては機能します。
変数名を取得するためにグローバルを使用する必要がある理由...以下のように使用できます。
$variableName = "ajaxmint";
echo getVarName('$variableName');
function getVarName($name) {
return str_replace('$','',$name);
}
getVarName()
機能を必要としません。;-)
'$variableName'
は変数の名前を文字列として返しません。あなたがでこのトリックを行うことができる場合getVarName($variableName);
、あなたは賛成票を獲得します:)
ユースケースが本当にわかりません... print_var_name($ foobar)と入力する場合、代わりにprint( "foobar")と入力するのが難しい(そして違う)のは何ですか?
これを関数で使用したとしても、変数のローカル名を取得するためです...
いずれにせよ、必要なものがあった場合のリフレクションマニュアルです。