Làm thế nào để có được một tên biến như một chuỗi trong PHP?


201

Nói rằng tôi có mã PHP này:

$FooBar = "a string";

Sau đó tôi cần một chức năng như thế này:

print_var_name($FooBar);

bản in nào:

FooBar

Bất kỳ ý tưởng làm thế nào để đạt được điều này? Điều này thậm chí có thể trong PHP?


9
Nếu bạn cần điều này cho bất cứ điều gì trừ việc gỡ lỗi, bạn đang làm điều gì đó sai nghiêm trọng. Trường hợp sử dụng của bạn là gì?
troelskn

10
Câu hỏi hay. Tôi cần điều tương tự để gỡ lỗi.
takeshin

17
+1 - Tôi cần điều này để tự động tạo phản hồi XML hoặc JSON từ một đối tượng PHP mô hình. Phải bọc đối tượng bên trong một rootName => modelObjectmảng có tên khác chỉ cần thêm độ sâu không cần thiết cho phản hồi. Mong muốn điều này được đưa vào khả năng phản ánh thời gian chạy của ngôn ngữ.
Anurag

4
Tôi cũng có nhu cầu này trong chức năng ghi nhật ký. Tôi muốn có thể làm như sau: log ($ didTheSystemBlowUp); Để xuất hiện trong tệp nhật ký như: $ didTheSystemBlowUp = 'chưa, nhưng rất sớm';
SeanDowney

4
Ngoài ra, điều này có thể hữu ích khi gọi var_dump () vì vậy khi bạn gọi cùng lúc trên một số biến, bạn không xuất tên var theo cách thủ công để phân biệt giữa các đầu ra của vardupms.
PHP

Câu trả lời:


37

Bạn có thể sử dụng get_dained_vars () để tìm tên của một biến có cùng giá trị với biến bạn đang cố gắng tìm tên của. Rõ ràng điều này sẽ không luôn luôn hoạt động, vì các biến khác nhau thường có cùng giá trị, nhưng đó là cách duy nhất tôi có thể nghĩ để làm điều này.

Chỉnh sửa: get_dained_vars () dường như không hoạt động chính xác, nó trả về 'var' vì $ var được sử dụng trong chính hàm. $ GLOBALS dường như hoạt động nên tôi đã thay đổi nó thành đó.

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

    return false;
}

Chỉnh sửa: để rõ ràng, không có cách nào tốt để làm điều này trong PHP, điều này có lẽ là do bạn không cần phải làm điều đó. Có lẽ có nhiều cách tốt hơn để làm những gì bạn đang cố gắng làm.


2
À Được làm chậm ;-) Nghĩ tương tự, nhưng sử dụng $ GLOBALS thay thế. Vì vậy, so sánh danh tính mang lại đúng với các giá trị vô hướng ($ a = 'foo'; $ b = 'foo'; khẳng định ($ a === $ b);)?
Argelbargel

Thực tế bây giờ tôi đã kiểm tra mã của mình, mã của tôi luôn trả về 'var' vì nó được sử dụng trong hàm. Khi tôi sử dụng $ GLOBALS thay vào đó, nó sẽ trả về tên biến chính xác vì một số lý do. Vì vậy, tôi sẽ thay đổi mã trên để sử dụng $ GLOBALS.
Jeremy Ruten

Yup, tôi nhận ra nhưng get_dained_vars () là đủ ta.
Gary Willoughby

2
Có rất nhiều trường hợp mã này sẽ không hoạt động như mong đợi.
troelskn

122
Mã này là HORRIBLY không chính xác. Kiểm tra xem f biến có giống với biến được gửi bởi VALUE là một ý tưởng rất ngu ngốc. Vô số biến là NULL tại bất kỳ điểm nào. Myriads được đặt thành 1. Điều này thật điên rồ.
Alex Weinstein

49

Tôi cũng không thể nghĩ ra cách nào để làm việc này một cách hiệu quả nhưng tôi đã nghĩ ra cách này. Nó hoạt động, cho các sử dụng hạn chế dưới đây.

nhún vai

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

Nó hoạt động dựa trên dòng gọi hàm, nơi nó tìm thấy đối số mà bạn đã truyền vào. Tôi cho rằng nó có thể được mở rộng để hoạt động với nhiều đối số, nhưng, như những người khác đã nói, nếu bạn có thể giải thích tình huống tốt hơn, một giải pháp khác có thể sẽ làm việc tốt hơn


2
Điều này hoạt động, nhưng chỉ khi hàm varName được xác định trong cùng một tệp với biến được tìm thấy.
rubo77

1
Ở đây bạn tìm thấy một triển khai tốt hơn hoạt động trên một số bao gồm: stackoverflow.com/a/19788805/1069083
rubo77

31

Bạn có thể xem xét thay đổi cách tiếp cận của bạn và sử dụng một tên biến?

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

sau đó bạn có thể

print($var_name);

để có được

FooBar

Đây là liên kết đến hướng dẫn sử dụng PHP về các biến số


42
Tôi đã làm việc với một hệ thống sử dụng các biến số rộng rãi. Hãy để tôi cảnh báo bạn, nó thực sự có mùi rất nhanh!
Icode4food

3
hầu hết các trường hợp người dùng muốn lấy tên và giá trị của một var. nghĩ "hàm debugvar ($ varname)" và anh ta dự định gọi nó là "debugvar ('foo')" để gỡ lỗi sẽ hiển thị "foo = 123". với biến số họ sẽ nhận được 'foo' không xác định.
gcb

Chỉ cần nhìn vào những gì bạn đang thực sự làm. Ngay trong ví dụ của bạn, bạn thực sự TẠO một biến $FooBarvới giá trị a stringchỉ cần đọc hướng dẫn của bạn. Đây là imho khủng khiếp. bạn không bao giờ gán cho biến $FooBarmột giá trị, nhưng nó ở đó. OUCH
Toskan

20

Không ai có vẻ đã đề cập đến những lý do cơ bản tại sao điều này là một) khó khăn và b) không khôn ngoan:

  • Một "biến" chỉ là một biểu tượng chỉ vào một cái gì đó khác. Trong PHP, bên trong nó trỏ đến một thứ gọi là "zval", thực sự có thể được sử dụng cho nhiều biến số cùng một lúc, vì chúng có cùng giá trị (PHP thực hiện một cái gì đó gọi là "copy-on-write" để $foo = $barkhông cần phải cấp phát thêm bộ nhớ ngay lập tức) hoặc bởi vì chúng đã được gán (hoặc được truyền cho một hàm) theo tham chiếu (ví dụ $foo =& $bar). Vì vậy, một zval không có tên.
  • Khi bạn truyền tham số cho hàm, bạn đang tạo một biến mới (ngay cả khi đó là tham chiếu). Bạn có thể vượt qua một cái gì đó ẩn danh, như "hello", nhưng một khi bên trong chức năng của bạn, đó là bất kỳ biến nào bạn đặt tên là. Điều này khá cơ bản để phân tách mã: nếu một hàm dựa vào cái mà một biến được sử dụng để gọi, thì nó sẽ giống như một gotohàm riêng biệt hơn.
  • Biến toàn cầu thường được coi là một ý tưởng tồi. Rất nhiều ví dụ ở đây cho rằng biến bạn muốn "phản ánh" có thể được tìm thấy $GLOBALS, nhưng điều này sẽ chỉ đúng nếu bạn cấu trúc mã của mình không tốt và các biến không nằm trong phạm vi chức năng hoặc đối tượng.
  • Tên biến có sẵn để giúp các lập trình viên đọc mã của họ. Đổi tên các biến để phù hợp hơn với mục đích của chúng là một cách thực hành tái cấu trúc rất phổ biến và toàn bộ vấn đề là nó không tạo ra sự khác biệt nào.

Bây giờ, tôi hiểu mong muốn này để gỡ lỗi (mặc dù một số cách sử dụng được đề xuất vượt xa điều đó), nhưng như một giải pháp tổng quát, nó không thực sự hữu ích như bạn nghĩ: nếu hàm gỡ lỗi của bạn nói biến của bạn được gọi là "$ file ", đó vẫn có thể là bất kỳ một trong số hàng chục biến" $ file "trong mã của bạn hoặc một biến mà bạn đã gọi là" $ filename "nhưng đang chuyển đến một hàm có tham số được gọi là" $ file ".

Một thông tin hữu ích hơn nhiều là trong mã của bạn, hàm gỡ lỗi được gọi từ đâu. Vì bạn có thể nhanh chóng tìm thấy điều này trong trình soạn thảo của mình, bạn có thể thấy biến nào bạn tự xuất ra và thậm chí có thể chuyển toàn bộ biểu thức vào đó trong một lần (ví dụ debug('$foo + $bar = ' . ($foo + $bar))).

Vì thế, bạn có thể sử dụng đoạn mã này ở đầu chức năng gỡ lỗi của mình:

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

Có một số câu trả lời tốt rồi. Vì vậy, đây chỉ là bi quan ngay cả khi đối mặt với thực tế.
a20

@ a20 Tất cả các câu trả lời đều có những cảnh báo nặng nề về thời điểm chúng có thể được sử dụng và khi nào chúng sẽ bị hỏng; không có gì là tìm kiếm đơn giản từ bất kỳ biến nào đến tên của nó, vì thực tế điều đó là không thể. Một số làm rất nhiều phản ánh sôi nổi cho mục đích gỡ lỗi, điều này là tốt; tuy nhiên, ý kiến của tôi cho rằng bạn tốt hơn hết là chỉ cần xuất số dòng và tự tìm kiếm dòng nguồn - hoặc sử dụng trình gỡ lỗi tương tác như XDebug.
IMSoP

14

Đây chính xác là những gì bạn muốn - đó là một chức năng "sao chép và thả vào" sẵn sàng để lặp lại tên của một var đã cho:

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

SỬ DỤNG: print_var_name ($ FooBar)

IN: FooBar

GỢI Ý Bây giờ bạn có thể đổi tên chức năng và nó vẫn sẽ hoạt động và cũng sử dụng chức năng nhiều lần trong một dòng! Cảm ơn @Cliffordlife


3
Thật tuyệt, cảm ơn vì điều này. Tôi đã sửa đổi dòng $ pat một chút $pat = '#(.*)'.__FUNCTION__.' *?\( *?(.*) *?\)(.*)#i';theo cách này. Tôi không quan tâm hàm gỡ lỗi này được gọi là gì và tôi nhận được chính xác những gì được truyền vào hàm, ví dụ $ xin chào, hoặc "xin chào" (Tôi đã bỏ kết quả $ khớp cho biến được truyền trong cùng một dòng)
Cliffordlife

1
Đoạn mã tuyệt vời! Cảm ơn! Tuy nhiên, nó dường như không hoạt động trong tất cả các trường hợp. Kết quả thử nghiệm trên Ubuntu 18.04 của tôi với php 7.2.19: Không hoạt động khi được sử dụng nhiều lần trên cùng một dòng mã, bất kể nó được sử dụng trong một hoặc các biểu thức riêng biệt, vì sau đó nó trả về tên của biến cuối cùng của hàng. Nếu nó được sử dụng trong cùng một biểu thức nhưng trên các dòng riêng biệt thì nó hoạt động. Được sử dụng trong các biểu thức khác nhau trên các dòng khác nhau, nó hoạt động.
Matty

1
Ngoài ra, chức năng đó phải ở trong một dòng mà không có "var_dump" - với print_var_name, echo, var_dumpđầu ra gửi kết hợp$variable); echo ' '; var_dump($variable
BG Bruno

13

Lucas trên PHP.net cung cấp một cách đáng tin cậy để kiểm tra nếu một biến tồn tại. Trong ví dụ của mình, anh ta lặp lại thông qua một bản sao của mảng biến toàn cục (hoặc một mảng có phạm vi) của các biến, thay đổi giá trị thành giá trị được tạo ngẫu nhiên và kiểm tra giá trị được tạo trong mảng được sao chép.

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

Vậy hãy thử đi:

$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

Hãy chắc chắn kiểm tra bài đăng của anh ấy trên PHP.net: http://php.net/manual/en/lingu.variables.php


Làm thế nào để bạn có được phạm vi hiện tại ở dạng mảng?
Sebastián Grignoli

Đẹp! Đối với tôi chỉ thiếu là break;khi tìm thấy bằng nhau trong foreach + Tôi đã sử dụng cấu trúc cơ bản có thể sử dụng để tự động nhận var_name nếu được xác định bên trong hàm. Nếu bạn thường xuyên Sao chép & Dán hoặc có ý tưởng tốt hơn để cải thiện nó, hãy sử dụngvariable_name( $variable, ( empty(__FUNCTION__) ? false : get_defined_vars() ) );
odie2

Đây có lẽ là cách nhanh nhất và sạch nhất để thực hiện công việc, gỡ lỗi có thể bao gồm các vấn đề về hiệu suất. Hàm sẽ trả về trực tiếp trong vòng lặp foreach thay vì chỉ gán mà không bị gián đoạn. Cho GLOBALS có thể lớn có thể là một cải tiến hiệu suất.
Giăng

13

Tôi đã thực hiện một chức năng kiểm tra cho lý do gỡ lỗi. Nó giống như print_r () trên steroid, giống như Krumo nhưng hiệu quả hơn một chút trên các vật thể. Tôi muốn thêm phát hiện tên var và đưa ra điều này, lấy cảm hứng từ bài đăng của Nick Presta trên trang này. Nó phát hiện bất kỳ biểu thức nào được truyền dưới dạng đối số, không chỉ tên biến.

Đây chỉ là chức năng bao bọc phát hiện biểu thức đã qua. Hoạt động trên hầu hết các trường hợp. Nó sẽ không hoạt động nếu bạn gọi hàm nhiều lần trong cùng một dòng mã.

Điều này hoạt động tốt: chết ( kiểm tra ($ this-> getUser () -> hasCredential ("xóa")) );

Kiểm tra () là hàm sẽ phát hiện biểu thức đã qua.

Chúng tôi nhận được: $ this-> getUser () -> hasCredential ("xóa")

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

}

Đây là một ví dụ về chức năng thanh tra (và lớp dInspect của tôi) đang hoạt động:

http://inspect.ip1.cc

Các văn bản bằng tiếng Tây Ban Nha trong trang đó, nhưng mã ngắn gọn và thực sự dễ hiểu.


1
errrm, không dựa vào bạn đã cài đặt trình gỡ lỗi NuSphare?
Mawg nói rằng phục hồi Monica

Tôi đã đăng một phiên bản đơn giản của mã này ở đó. Ngoài ra tôi đã sửa đổi câu trả lời này. Nó nên chạy trên mọi triển khai PHP5 ngay bây giờ.
Sebastián Grignoli

Khéo léo như thế này là lý do tại sao tôi cười mỗi khi tôi thấy mọi người nói "không thể làm được" hoặc "không thể", bao gồm cả chính Rasmus trong trường hợp này. Kudos cho Sebastián và bất cứ ai khác có thể đã đóng góp cho câu trả lời này.
Cú đêm

1
Cảm ơn Night Owl, nhưng tôi khẳng định rằng đây không phải là bằng chứng viên đạn (như câu trả lời, nó sẽ thất bại nếu chức năng "tests ()" của tôi được gọi nhiều lần trong một dòng!). Tôi sẽ không bao giờ sử dụng điều này trong sản xuất. Nó chỉ dành cho chức năng kiểm tra gỡ lỗi không bao giờ đến được máy chủ sản xuất.
Sebastián Grignoli

7

Từ php.net

@Alexandre - giải pháp ngắn

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

@Lu - cách sử dụng

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

4

Nhiều người trả lời câu hỏi về tính hữu ích của việc này. Tuy nhiên, nhận được một tài liệu tham khảo cho một biến có thể rất hữu ích. Đặc biệt trong các trường hợp với các đối tượng và $ này . Giải pháp của tôi hoạt động với các đối tượng và cũng như các đối tượng được xác định thuộc tính:

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

Ví dụ cho những điều trên:

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

2

Được điều chỉnh từ các câu trả lời ở trên cho nhiều biến số, với hiệu suất tốt, chỉ cần quét $ GLOBALS cho nhiều biến

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
        )

)

1

Nếu biến có thể hoán đổi cho nhau, bạn phải có logic ở đâu đó xác định biến nào sẽ được sử dụng. Tất cả những gì bạn cần làm là đặt tên biến $variabletrong logic đó trong khi bạn đang làm mọi thứ khác.

Tôi nghĩ rằng tất cả chúng ta đều có một thời gian khó hiểu những gì bạn cần điều này cho. Mẫu mã hoặc giải thích về những gì bạn đang thực sự cố gắng để làm sức giúp đỡ, nhưng tôi nghi ngờ bạn cách đang, cách overthinking này.


1

Tôi thực sự có một trường hợp sử dụng hợp lệ cho việc này.

Tôi có chức năng cacheVariable ($ var) (ok, tôi có bộ đệm chức năng ($ key, $ value), nhưng tôi muốn có một chức năng như đã đề cập).

Mục đích là để làm:

$colour = 'blue';
cacheVariable($colour);

...

// another session

...

$myColour = getCachedVariable('colour');

Tôi đã thử với

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
}

Tôi cũng đã thử với

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

Nhưng điều này cũng thất bại ... :(

Chắc chắn, tôi có thể tiếp tục thực hiện bộ đệm ('màu', $ color), nhưng tôi lười, bạn biết đấy ...;)

Vì vậy, điều tôi muốn là một hàm lấy tên ORIGINAL của một biến, vì nó được truyền cho một hàm. Bên trong chức năng không có cách nào tôi có thể biết điều đó, dường như. Việc vượt qua get_dained_vars () bằng cách tham chiếu trong ví dụ thứ hai ở trên đã giúp tôi (Cảm ơn Jean-Jacques Guegan vì ý tưởng đó) phần nào. Hàm sau bắt đầu hoạt động, nhưng nó vẫn chỉ trả về biến cục bộ ('biến', không phải 'màu').

Tôi chưa thử sử dụng get_func_args () và get_func_arg (), $ {} - các cấu trúc và khóa () kết hợp, nhưng tôi cho rằng nó cũng sẽ thất bại.


1
Vấn đề rất cơ bản là bạn chuyển các giá trị vào các hàm chứ không phải các biến . Các biến là tạm thời và đặc biệt cho phạm vi của chúng. Thường thì tên biến có thể không phải là khóa bạn muốn lưu trữ giá trị bên dưới và thường thì bạn sẽ khôi phục nó thành một biến có tên khác (như bạn làm trong ví dụ của mình). Nếu bạn thực sự quá lười biếng để lặp lại tên của khóa để ghi nhớ biến, hãy sử dụng cacheVariable(compact('color')).
lừa dối

1

Tôi có cái này:

  debug_echo(array('$query'=>$query, '$nrUsers'=>$nrUsers, '$hdr'=>$hdr));

Tôi thích điều này:

  debug_echo($query, $nrUsers, $hdr);

Hàm hiện có hiển thị một hộp màu vàng với viền ngoài màu đỏ và hiển thị từng biến theo tên và giá trị. Giải pháp mảng hoạt động nhưng hơi phức tạp để gõ khi cần thiết.

Đó là trường hợp sử dụng của tôi và vâng, nó phải làm với việc gỡ lỗi. Tôi đồng ý với những người đặt câu hỏi về việc sử dụng nó.


1

Đây là giải pháp của tôi dựa trên Jeremy Ruten

class DebugHelper {

    function printVarNames($systemDefinedVars, $varNames) {
        foreach ($systemDefinedVars as $var=>$value) {
            if (in_array($var, $varNames )) {
                var_dump($var);
                var_dump($value);
            }
        }
    }
}

sử dụng nó

DebugHelper::printVarNames(
    $systemDefinedVars = get_defined_vars(),
    $varNames=array('yourVar00', 'yourVar01')
);

0

Tại sao bạn không xây dựng một chức năng đơn giản và NÓI?

/**
 * 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' );

0

Tôi đã tìm kiếm điều này nhưng chỉ cần quyết định chuyển tên vào, tôi thường có tên trong bảng tạm.

function VarTest($my_var,$my_var_name){
    echo '$'.$my_var_name.': '.$my_var.'<br />';
}

$fruit='apple';
VarTest($fruit,'fruit');

0

Bạn có thể sử dụng compact () để đạt được điều này.

$FooBar = "a string";

$newArray = compact('FooBar');

Điều này sẽ tạo ra một mảng kết hợp với tên biến là khóa. Sau đó, bạn có thể lặp qua mảng bằng tên khóa mà bạn cần.

foreach($newarray as $key => $value) {
    echo $key;
}

2
Thật tuyệt nhưng bạn phải biết tên của biến để sử dụng nó. OP đang tìm cách xác định tên biến theo chương trình.
một lập trình viên

0

Tôi nghĩ rằng bạn muốn biết tên biến với giá trị của nó. Bạn có thể sử dụng một mảng kết hợp để đạt được điều này.

sử dụng tên biến cho các khóa mảng:

$vars = array('FooBar' => 'a string');

Khi bạn muốn lấy tên biến, hãy sử dụng array_keys($vars), nó sẽ trả về một mảng các tên biến được sử dụng trong $varsmảng của bạn làm khóa.


Chậm hơn nhiều so với các phương pháp khai báo biến thông thường hơn.
David Spector

0

Tôi biết điều này đã cũ và đã được trả lời nhưng tôi thực sự đang tìm kiếm điều này. Tôi đang đăng câu trả lời này để tiết kiệm cho mọi người một chút thời gian tinh chỉnh một số câu trả lời.

Lựa chọn 1:

$data = array('$FooBar');  

$vars = [];  
$vars = preg_replace('/^\\$/', '', $data); 

$varname = key(compact($vars));  
echo $varname;

Bản in:

FooBar

Vì bất kỳ lý do gì bạn sẽ thấy mình trong một tình huống như thế này, nó thực sự hoạt động.

.
Lựa chọn 2:

$FooBar = "a string";  

$varname = trim(array_search($FooBar, $GLOBALS), " \t.");  
echo $varname;

Nếu $FooBargiữ một giá trị duy nhất, nó sẽ in 'FooBar'. Nếu $FooBartrống hoặc null, nó sẽ in tên của chuỗi rỗng hoặc null đầu tiên mà nó tìm thấy.

Nó có thể được sử dụng như vậy:

if (isset($FooBar) && !is_null($FooBar) && !empty($FooBar)) {
    $FooBar = "a string";
    $varname = trim(array_search($FooBar, $GLOBALS), " \t.");
}

0

Đây là cách tôi đã làm

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

Sử dụng

$city  = "San Francisco";
echo getVar($city); // city

Lưu ý: một số phiên bản PHP 7 sẽ không hoạt động đúng do lỗi array_searchvới $GLOBALS, tuy nhiên tất cả các phiên bản khác sẽ hoạt động.

Xem https://3v4l.org/UMW7V này


-1

Sử dụng điều này để tách các biến người dùng khỏi toàn cầu để kiểm tra biến tại thời điểm này.

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

@IMSoP Đánh giá theo đầu ra của print implode( ' ', array_keys( $GLOBALS ));nó trông giống như một giả định sai lầm về số lượng toàn cầu "mặc định". Trên hệ thống của tôi có bảy superglobals: $ _GET, $ _POST, $ _COOKIE, $ _FILES, $ _ENV, $ _REQUEST, $ _SERVER. Và cũng có argv và argc. Vì vậy, độ lệch phải là 9. Và không có điểm nào trong việc chỉ định tham số thứ ba (độ dài) vì mặc định chỉ là chạy đến cuối mảng.
Jeff

-2

Nó có thể được coi là nhanh chóng và bẩn thỉu, nhưng sở thích cá nhân của riêng tôi là sử dụng một chức năng / phương pháp như thế này:

public function getVarName($var) {      
  $tmp = array($var => '');
  $keys = array_keys($tmp);
  return trim($keys[0]);
}

về cơ bản, nó chỉ tạo ra một mảng kết hợp có chứa một phần tử null / rỗng, sử dụng làm khóa cho biến mà bạn muốn đặt tên.

sau đó chúng tôi nhận được giá trị của khóa đó bằng mảng_key và trả về nó.

rõ ràng điều này trở nên lộn xộn nhanh chóng và sẽ không được mong muốn trong môi trường sản xuất, nhưng nó hoạt động cho vấn đề được trình bày.


1
Đó là giá trị của biến, không phải tên của biến. Như đã chỉ ra ở nơi khác, tên không thể di chuyển qua các ranh giới chức năng.
Owen Beresford

3
trừ đi một vì hàm này thực sự không làm gì ngoài việc trả lại số trang trí ($ var);
Alexar

-3

tại sao chúng ta phải sử dụng toàn cầu để có được tên biến ... chúng ta có thể sử dụng đơn giản như dưới đây.

    $variableName = "ajaxmint";

    echo getVarName('$variableName');

    function getVarName($name) {
        return str_replace('$','',$name);
    }

6
Vì OP không biết tên biến. Nếu anh ta làm thế, anh ta sẽ không cần một getVarName()chức năng. ;-)
FtDRbwLXw6

1
Điều này không trả về tên của một biến dưới dạng chuỗi, vì '$variableName'đã là một chuỗi, không phải là một biến. Nếu bạn có thể thực hiện thủ thuật này với getVarName($variableName);, bạn sẽ nhận được upvote :)
Daniel W.

-4

Tôi thực sự không thấy trường hợp sử dụng ... Nếu bạn sẽ gõ print_var_name ($ foobar), điều gì quá khó (và khác biệt) về việc gõ print ("foobar") thay vào đó?

Bởi vì ngay cả khi bạn sử dụng hàm này trong hàm, bạn sẽ nhận được tên cục bộ của biến ...

Trong mọi trường hợp, đây là hướng dẫn phản chiếu trong trường hợp có thứ bạn cần trong đó.


In ("foobar") sẽ không xử lý các lọ khác.
Gary Willoughby

7
Trường hợp sử dụng: bạn có một vài điểm gỡ lỗi trong mã trả về việc bán phá giá cùng giá trị. Làm thế nào để bạn biết cái nào được thực hiện đầu tiên? In một nhãn là rất hữu ích sau đó.
takeshin

Sau đó, bạn đã không thực hiện đủ chương trình. Hầu hết các ngôn ngữ tôi đã đi qua có một số cách để làm điều này, thường là đơn giản.
b01

@ b01 Tôi đã làm rất nhiều. Tôi hoàn toàn biết rằng có nhiều ngôn ngữ cho phép điều này, nhưng bản thân nó không có nghĩa gì nhiều. Nhiều ngôn ngữ cung cấp một số cách để thực hiện goto dễ dàng và điều đó không có nghĩa là bạn nên sử dụng nó để tránh viết điều khiển luồng thích hợp. Đây là một trường hợp tương tự theo quan điểm của tôi. Tôi không nghi ngờ có những trường hợp chính đáng, và đó là lý do tại sao tôi tự hỏi về các trường hợp sử dụng thích hợp cho nó.
Vinko Vrsalovic
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.