วิธีรับชื่อตัวแปรเป็นสตริงใน PHP


201

สมมติว่าฉันมีรหัส PHP นี้:

$FooBar = "a string";

ฉันต้องการฟังก์ชั่นเช่นนี้:

print_var_name($FooBar);

ซึ่งพิมพ์:

FooBar

ความคิดใด ๆ วิธีการบรรลุสิ่งนี้? เป็นไปได้ใน PHP หรือไม่


9
หากคุณต้องการสิ่งนี้ยกเว้นการดีบักคุณกำลังทำสิ่งผิดปกติอย่างรุนแรง กรณีการใช้งานของคุณคืออะไร?
troelskn

10
คำถามที่ดี. ฉันต้องการแบบเดียวกันสำหรับการดีบัก
takeshin

17
+1 - ฉันต้องการสิ่งนี้สำหรับการสร้าง XML หรือการตอบสนอง JSON อัตโนมัติจากวัตถุ PHP โมเดล การห่อวัตถุภายในrootName => modelObjectอาเรย์ที่มีชื่ออีกอันนั้นเพิ่มความลึกที่ไม่จำเป็นให้กับการตอบสนอง อยากให้สิ่งนี้ถูกอบเข้ากับความสามารถในการสะท้อนกลับของภาษา
Anurag

4
ฉันยังต้องการสิ่งนี้ในฟังก์ชั่นการบันทึก ฉันอยากจะทำสิ่งต่อไปนี้: log ($ didTheSystemBlowUp); ในการปรากฏในล็อกไฟล์เช่น: $ didTheSystemBlowUp = 'ยังไม่ได้ แต่เร็ว ๆ นี้';
SeanDowney

4
นอกจากนี้ยังมีประโยชน์เมื่อเรียก var_dump () ดังนั้นเมื่อคุณโทรในเวลาเดียวกันกับตัวแปรหลายตัวคุณไม่มีชื่อ var output ด้วยตนเองเพื่อแยกความแตกต่างระหว่างเอาต์พุตของ vardupms
PHPst

คำตอบ:


37

คุณสามารถใช้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 ซึ่งอาจเป็นเพราะคุณไม่ควรทำ อาจมีวิธีที่ดีกว่าในการทำสิ่งที่คุณพยายามจะทำ


2
อ่า เคยช้า ;-) คิดเหมือนกัน แต่ใช้ $ GLOBALS แทน ดังนั้นการเปรียบเทียบตัวตนให้ผลเป็นจริงสำหรับเท่ากับค่าสเกลาร์ ($ a = 'foo'; $ b = 'foo'; ยืนยัน ($ a === $ b);)
Argelbargel

ที่จริงตอนนี้ฉันได้ทดสอบโค้ดแล้วโค้ดของฉันคืน 'var' เสมอเพราะมันถูกใช้ในฟังก์ชัน เมื่อฉันใช้ $ GLOBALS แทนมันจะคืนชื่อตัวแปรที่ถูกต้องด้วยเหตุผลบางอย่าง ดังนั้นฉันจะเปลี่ยนรหัสข้างต้นเพื่อใช้ $ GLOBALS
Jeremy Ruten

ใช่ฉันรู้แล้ว แต่ get_defined_vars () เพียงพอแล้ว
Gary Willoughby

2
มีหลายกรณีที่รหัสนี้จะไม่ทำงานตามที่คาดไว้
troelskn

122
รหัสนี้ไม่ถูกต้อง HORRIBLY การตรวจสอบเพื่อดูว่าตัวแปรเป็นเช่นเดียวกับที่ส่งโดย VALUE เป็นแนวคิดที่โง่มาก ตัวแปรจำนวนมากเป็น NULL ณ จุดใด ๆ Myriads ถูกตั้งค่าเป็น 1 นี่มันบ้าไปแล้ว
Alex Weinstein

49

ฉันไม่สามารถคิดวิธีที่จะทำสิ่งนี้ได้อย่างมีประสิทธิภาพ แต่ฉันคิดวิธีนี้ขึ้นมา ใช้งานได้สำหรับการใช้งานที่ จำกัด ด้านล่าง

ยัก

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

มันใช้งานได้ตามบรรทัดที่เรียกว่าฟังก์ชันซึ่งพบอาร์กิวเมนต์ที่คุณส่งผ่านฉันคิดว่ามันสามารถขยายให้ทำงานกับอาร์กิวเมนต์หลายตัว แต่อย่างที่คนอื่นพูดถ้าคุณสามารถอธิบายสถานการณ์ได้ดีขึ้น ทำงานได้ดีขึ้น


2
สิ่งนี้ใช้ได้ผลก็ต่อเมื่อฟังก์ชัน varName ถูกกำหนดในไฟล์เดียวกับตัวแปรที่จะพบ
rubo77

1
นี่คุณจะพบการดำเนินงานที่ดีกว่าที่ผลงานในช่วงหลายรวมถึง: stackoverflow.com/a/19788805/1069083
rubo77

31

คุณอาจพิจารณาเปลี่ยนวิธีการของคุณและใช้ชื่อตัวแปรตัวแปร?

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

จากนั้นคุณสามารถทำได้

print($var_name);

เพื่อรับ

FooBar

นี่คือลิงค์ไปยังคู่มือ PHP เกี่ยวกับตัวแปรตัวแปร


42
ฉันทำงานกับระบบที่ใช้ตัวแปรตัวแปรอย่างกว้างขวาง ให้ฉันเตือนคุณมันจะส่งกลิ่นเร็วมากจริงๆ!
Icode4food

3
กรณีส่วนใหญ่ที่ผู้ใช้ต้องการรับชื่อและค่าของ var คิดว่า "debugvar ฟังก์ชัน ($ varname)" และเขาตั้งใจจะเรียกมันว่า "debugvar ('foo')" ดังนั้น debug จะแสดง "foo = 123" กับตัวแปรตัวแปรพวกเขาจะได้รับ 'foo' ไม่ได้ถูกกำหนด
gcb

แค่มองสิ่งที่คุณกำลังทำอยู่ ในตัวอย่างของคุณคุณสร้างตัวแปร$FooBarด้วยค่าที่a stringอ่านคู่มือของคุณ นี่คือ imho ที่น่ากลัว คุณไม่เคยกำหนดค่าตัวแปร$FooBarแต่มี OUCH
Toskan

20

ดูเหมือนจะไม่มีใครพูดถึงเหตุผลพื้นฐานว่าทำไมเรื่องนี้จึงยากและข) ไม่ฉลาด:

  • "ตัวแปร" เป็นเพียงสัญลักษณ์ชี้ไปที่สิ่งอื่น ใน PHP มันชี้ไปที่สิ่งที่เรียกว่า "zval" ซึ่งสามารถนำมาใช้กับตัวแปรหลายตัวพร้อมกันได้อย่างแท้จริงเนื่องจากพวกเขามีค่าเท่ากัน (PHP ใช้สิ่งที่เรียกว่า "copy-on-write" ดังนั้นจึง$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'];

มีคำตอบที่ดีอยู่แล้ว ดังนั้นนี่เป็นเพียงแค่การมองโลกในแง่ร้ายแม้ต้องเผชิญกับความจริง
a20

@ a20 คำตอบทั้งหมดมีข้อแม้อย่างหนักเกี่ยวกับเวลาที่พวกเขาสามารถใช้และเมื่อพวกเขาจะแตก none คือการค้นหาอย่างง่ายจากตัวแปรใด ๆ ไปยังชื่อของมันเพราะในความเป็นจริงเป็นไปไม่ได้ บางคนทำภาพสะท้อนที่ขี้ขลาดมากมายเพื่อจุดประสงค์ในการดีบั๊กซึ่งก็ดี อย่างไรก็ตามความคิดเห็นของฉันอยู่ที่ว่าคุณจะดีกว่าเพียงแค่แสดงหมายเลขบรรทัดและค้นหาบรรทัดของแหล่งที่มาด้วยตัวคุณเองหรือใช้ดีบักเกอร์แบบโต้ตอบเช่น XDebug
IMSoP

14

นี่คือสิ่งที่คุณต้องการอย่างแน่นอน - ฟังก์ชั่น "คัดลอกและวาง" พร้อมที่จะสะท้อนชื่อ 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 trim($var);
}

การใช้งาน: print_var_name ($ FooBar)

พิมพ์: FooBar

คำแนะนำ ตอนนี้คุณสามารถเปลี่ยนชื่อฟังก์ชั่นและมันจะยังคงใช้งานได้และใช้ฟังก์ชั่นหลายครั้งในหนึ่งบรรทัด ขอบคุณ @Cliffordlife


3
เยี่ยมยอดขอบคุณสำหรับสิ่งนี้ ฉันแก้ไข $ pat line เล็กน้อย$pat = '#(.*)'.__FUNCTION__.' *?\( *?(.*) *?\)(.*)#i';ด้วยวิธีนี้ฉันไม่สนใจสิ่งที่เรียกว่าฟังก์ชั่นการแก้ปัญหานี้และฉันได้รับสิ่งที่ถูกส่งผ่านไปยังฟังก์ชั่นเช่น $ hello หรือ "hello" (ฉันลดการจับคู่ $ สำหรับตัวแปรที่ส่งผ่าน ใน, ในบรรทัดเดียวกัน)
Cliffordlife

1
โค้ดที่ยอดเยี่ยม! ขอบคุณ! อย่างไรก็ตามดูเหมือนว่ามันจะไม่ทำงานในทุกกรณี ผลลัพธ์ของการทดสอบบน Ubuntu ของฉัน 18.04 ด้วย php 7.2.19: ไม่ทำงานเมื่อใช้รหัสบรรทัดเดียวกันหลายครั้งโดยไม่คำนึงถึงว่ามันถูกใช้ในนิพจน์เดียวหรือแยกกันเพราะมันส่งคืนชื่อตัวแปรสุดท้ายของ ไลน์. ถ้ามันถูกใช้ในนิพจน์เดียวกัน แต่ใช้กับบรรทัดที่แยกกัน ใช้ในนิพจน์ต่าง ๆ ในบรรทัดที่ต่างกัน
Matty

1
ฟังก์ชั่นนั้นควรอยู่ในหนึ่งบรรทัดโดยไม่มี "var_dump" - พร้อมชุดprint_var_name, echo, var_dumpผลลัพธ์ส่งออก$variable); echo ' '; var_dump($variable
BG Bruno

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


คุณจะรับขอบเขตปัจจุบันในรูปแบบอาร์เรย์ได้อย่างไร
Sebastián Grignoli

ดี! สำหรับฉันที่ขาดหายไปก็คือbreak;เมื่อพบว่าเท่ากันใน foreach + ฉันใช้โครงสร้างพื้นฐานที่ใช้งานได้โดยอัตโนมัติเพื่อรับ var_name เช่นกันหากกำหนดไว้ภายในฟังก์ชั่น หากคุณมักจะคัดลอกและวางหรือมีความคิดที่ดีกว่าในการปรับปรุงให้ใช้variable_name( $variable, ( empty(__FUNCTION__) ? false : get_defined_vars() ) );
odie2

นี่อาจเป็นวิธีที่เร็วและสะอาดที่สุดในการทำงานการดีบักอาจรวมถึงปัญหาด้านประสิทธิภาพ ฟังก์ชั่นควรกลับโดยตรงในลูป foreach แทนที่จะเพียงกำหนดโดยไม่หยุดชะงัก เมื่อพิจารณาจาก GLOBALS นั้นมีขนาดใหญ่ซึ่งสามารถปรับปรุงประสิทธิภาพได้ค่อนข้างมาก
จอห์น

13

ฉันทำฟังก์ชั่นการตรวจสอบด้วยเหตุผลในการแก้ไขข้อบกพร่อง มันเหมือนกับ print_r () บนสเตียรอยด์เหมือน Krumo แต่มีประสิทธิภาพมากกว่าบนวัตถุ ฉันต้องการเพิ่มการตรวจจับชื่อ var และออกมาพร้อมสิ่งนี้แรงบันดาลใจจากโพสต์ของ Nick Presta ในหน้านี้ มันตรวจจับการแสดงออกใด ๆ ที่ส่งผ่านเป็นอาร์กิวเมนต์ไม่เพียง แต่ชื่อตัวแปร

นี่เป็นเพียงฟังก์ชัน wrapper ที่ตรวจจับนิพจน์ที่ส่งผ่าน ทำงานในกรณีส่วนใหญ่ จะไม่ทำงานหากคุณเรียกใช้ฟังก์ชันมากกว่าหนึ่งครั้งในรหัสบรรทัดเดียวกัน

ใช้งานได้ดี: ตาย ( ตรวจสอบ ($ 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

ข้อความเป็นภาษาสเปนในหน้านั้น แต่รหัสกระชับและเข้าใจง่าย


1
errrm นั่นไม่ได้ขึ้นอยู่กับคุณว่ามีการติดตั้งดีบักเกอร์ NuSphare หรือไม่?
Mawg กล่าวว่าคืนสถานะโมนิก้า

ฉันโพสต์โค้ดนี้ในเวอร์ชันที่ง่ายขึ้นแล้ว นอกจากนี้ฉันแก้ไขคำตอบนี้ มันควรจะทำงานในทุก ๆ การติดตั้ง PHP5 ทันที
Sebastián Grignoli

ความฉลาดเช่นนี้คือสาเหตุที่ฉันยิ้มทุกครั้งที่มีคนพูดว่า "ทำไม่ได้" หรือ "ไม่ได้" ซึ่งรวมถึงแม้แต่ราสมุสเองในกรณีนี้ ขอชื่นชมเซบาสเตียนและคนอื่น ๆ ที่อาจมีส่วนทำให้คำตอบนี้
Night Owl

1
ขอบคุณ Night Owl แต่ฉันยืนยันว่านี่ไม่ใช่หลักฐานกระสุน (ตามคำตอบระบุว่าจะล้มเหลวหากฟังก์ชัน "inspect ()" ของฉันถูกเรียกมากกว่าหนึ่งครั้งในบรรทัดเดียว! ฉันจะไม่ใช้สิ่งนี้ในการผลิต มันเป็นเพียงฟังก์ชั่นการตรวจสอบการดีบักที่ไม่ควรไปถึงเซิร์ฟเวอร์ที่ใช้งานจริง
Sebastián Grignoli

7

จาก 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
?>

4

หลายคนตอบคำถามเกี่ยวกับประโยชน์ของสิ่งนี้ อย่างไรก็ตามการได้รับการอ้างอิงสำหรับตัวแปรนั้นมีประโยชน์มาก โดยเฉพาะในกรณีที่มีวัตถุและ$ นี้ โซลูชันของฉันทำงานกับวัตถุและเป็นวัตถุที่กำหนดคุณสมบัติเช่นกัน:

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

2

ดัดแปลงมาจากคำตอบข้างบนสำหรับตัวแปรหลายตัวพร้อมกับประสิทธิภาพที่ดีเพียง $ 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
        )

)

1

หากตัวแปรนั้นสามารถใช้ร่วมกันได้คุณจะต้องมีตรรกะที่ไหนสักแห่งที่กำหนดว่าจะใช้ตัวแปรตัวใด สิ่งที่คุณต้องทำคือใส่ชื่อตัวแปร$variableภายในตรรกะนั้นในขณะที่คุณทำทุกอย่างอื่น

ฉันคิดว่าเราทุกคนมีเวลายากที่จะเข้าใจว่าคุณต้องการสิ่งนี้เพื่ออะไร โค้ดตัวอย่างหรือคำอธิบายเกี่ยวกับสิ่งที่คุณพยายามทำจริง ๆอาจช่วยได้ แต่ฉันสงสัยว่าคุณมีวิธีคิดแบบนี้


1

ฉันมีกรณีการใช้งานจริงสำหรับสิ่งนี้

ฉันมีฟังก์ชั่น cacheVariable ($ var) (ตกลงฉันมีฟังก์ชั่นแคช ($ 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));
}

แต่สิ่งนี้ก็ล้มเหลวเช่นกัน ... :(

แน่นอนว่าฉันสามารถทำแคช ('color', $ color) ต่อไป แต่ฉันขี้เกียจคุณก็รู้ ... ;)

ดังนั้นสิ่งที่ฉันต้องการคือฟังก์ชั่นที่ได้รับชื่อเดิมของตัวแปรตามที่มันถูกส่งผ่านไปยังฟังก์ชั่น ภายในฟังก์ชั่นไม่มีทางที่ฉันจะรู้ได้อย่างที่เห็น การผ่าน get_defined_vars () โดยการอ้างอิงในตัวอย่างที่สองด้านบนช่วยฉันได้ (ขอบคุณ Jean-Jacques Guegan สำหรับความคิดนั้น) ฟังก์ชันหลังเริ่มทำงาน แต่ก็ยังคงส่งคืนเฉพาะตัวแปรภายในเครื่อง ('ตัวแปร' ไม่ใช่ 'สี')

ฉันยังไม่ได้ลองใช้ get_func_args () และ get_func_arg (), $ {} - โครงสร้างและคีย์ () รวมกัน แต่ฉันคิดว่ามันจะล้มเหลวเช่นกัน


1
ปัญหาพื้นฐานมากคือคุณผ่านค่าเข้าฟังก์ชั่นไม่ตัวแปร ตัวแปรชั่วคราวและโดยเฉพาะอย่างยิ่งในขอบเขตของพวกเขา บ่อยครั้งที่ชื่อตัวแปรอาจไม่ใช่คีย์ที่คุณต้องการแคชค่าภายใต้และบ่อยครั้งที่คุณจะกู้คืนเป็นตัวแปรที่มีชื่อแตกต่างกันอยู่แล้ว (เช่นที่คุณทำในตัวอย่างของคุณ) cacheVariable(compact('color'))หากคุณจริงๆขี้เกียจเกินไปที่จะทำซ้ำชื่อของคีย์ที่จะจำตัวแปรโดยใช้
หลอก

1

ฉันมีสิ่งนี้:

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

ฉันต้องการสิ่งนี้:

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

ฟังก์ชั่นที่มีอยู่จะแสดงกล่องสีเหลืองพร้อมเค้าร่างสีแดงและแสดงตัวแปรแต่ละตัวตามชื่อและค่า วิธีการแก้ปัญหาอาร์เรย์ทำงาน แต่มีความซับซ้อนเล็กน้อยในการพิมพ์เมื่อมีความจำเป็น

เป็นกรณีการใช้งานของฉันและใช่มันเกี่ยวข้องกับการดีบัก ฉันเห็นด้วยกับผู้ที่สงสัยการใช้งานเป็นอย่างอื่น


1

นี่คือทางออกของฉันตาม 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')
);

0

ทำไมคุณไม่สร้างฟังก์ชั่นง่าย ๆ แล้วเล่าให้ฟัง?

/**
 * 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

ฉันกำลังมองหาสิ่งนี้ แต่เพิ่งตัดสินใจส่งชื่อเข้ามาฉันมักจะมีชื่อในคลิปบอร์ดอยู่ดี

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

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

0

คุณสามารถใช้ compact () เพื่อทำสิ่งนี้

$FooBar = "a string";

$newArray = compact('FooBar');

สิ่งนี้จะสร้างอาเรย์แบบเชื่อมโยงที่มีชื่อตัวแปรเป็นคีย์ จากนั้นคุณสามารถวนซ้ำอาร์เรย์โดยใช้ชื่อคีย์ที่คุณต้องการ

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

2
เยี่ยม แต่คุณต้องรู้ชื่อของตัวแปรที่จะใช้ OP กำลังมองหาชื่อตัวแปรโดยทางโปรแกรม
coder

0

ฉันคิดว่าคุณต้องการทราบชื่อตัวแปรด้วยค่าของมัน คุณสามารถใช้อาเรย์แบบเชื่อมโยงเพื่อให้ได้สิ่งนี้

ใช้ชื่อตัวแปรสำหรับคีย์อาร์เรย์:

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

เมื่อคุณต้องการได้รับชื่อตัวแปรให้ใช้array_keys($vars)มันจะส่งกลับอาร์เรย์ของชื่อตัวแปรเหล่านั้นที่ใช้ใน$varsอาร์เรย์เป็นคีย์


ช้ากว่าวิธีปกติมากในการประกาศตัวแปร
David Spector

0

ฉันรู้ว่านี่เก่าและตอบแล้ว แต่จริง ๆ แล้วฉันกำลังมองหาสิ่งนี้ ฉันโพสต์คำตอบนี้เพื่อช่วยผู้คนประหยัดเวลาในการปรับคำตอบ

ตัวเลือกที่ 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ว่างเปล่าหรือเป็นโมฆะมันจะพิมพ์ชื่อของสตริงที่ว่างเปล่าแรกหรือสตริงที่พบ

มันสามารถใช้เป็นเช่นนี้:

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

0

นี่คือวิธีที่ฉันทำ

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นี้


-1

ใช้สิ่งนี้เพื่อแยกตัวแปรผู้ใช้จากส่วนกลางเพื่อตรวจสอบตัวแปรในขณะนี้

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 ดูจากผลลัพธ์ของprint implode( ' ', array_keys( $GLOBALS ));มันดูเหมือนว่ามีข้อผิดพลาดเกี่ยวกับจำนวนของ "ค่าเริ่มต้น" แบบกลม ในระบบของฉันมีเจ็ด superglobals: $ _GET, $ _POST, $ _COOKIE, $ _FILES, $ _ENV, $ _REQUEST, $ _SERVER และยังมี argv และ argc ดังนั้นอ็อฟเซ็ตควรเป็น 9 และไม่มีจุดใดในการระบุพารามิเตอร์ที่สาม (ความยาว) เนื่องจากค่าเริ่มต้นคือการเรียกใช้จนถึงจุดสิ้นสุดของอาร์เรย์
Jeff

-2

อาจถือว่ารวดเร็วและสกปรก แต่ความชอบส่วนตัวของฉันคือการใช้ฟังก์ชั่น / วิธีดังนี้:

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

โดยพื้นฐานแล้วมันเพิ่งสร้างอาเรย์แบบเชื่อมโยงที่มีองค์ประกอบหนึ่งเป็นโมฆะ / ว่างเปล่าโดยใช้เป็นตัวแปรที่คุณต้องการชื่อ

จากนั้นเราจะได้รับค่าของคีย์นั้นโดยใช้ array_keys แล้วส่งคืน

เห็นได้ชัดว่านี่ยุ่งอย่างรวดเร็วและไม่เป็นที่ต้องการในสภาพแวดล้อมการผลิต แต่ใช้ได้กับปัญหาที่นำเสนอ


1
นั่นคือค่าของตัวแปรไม่ใช่ชื่อของตัวแปร ตามที่ระบุไว้ที่อื่นชื่อไม่ได้พกพาข้ามขอบเขตของฟังก์ชัน
Owen Beresford

3
ลบหนึ่งเพราะฟังก์ชั่นนี้ไม่ได้ทำอะไรเลยนอกจากการคืนค่า trim ($ var);
Alexar

-3

ทำไมเราต้องใช้ globals เพื่อรับชื่อตัวแปร ... เราสามารถใช้แบบด้านล่างได้

    $variableName = "ajaxmint";

    echo getVarName('$variableName');

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

6
เนื่องจาก OP ไม่ทราบชื่อตัวแปร ถ้าเขาทำเขาจะไม่ต้องการgetVarName()ฟังก์ชั่น ;-)
FtDRbwLXw6

1
สิ่งนี้ไม่ส่งคืนชื่อของตัวแปรเป็นสตริงเนื่องจาก'$variableName'เป็นสตริงอยู่แล้วไม่ใช่ตัวแปร หากคุณสามารถทำเคล็ดลับนี้กับgetVarName($variableName);คุณจะได้รับ upvote :)
แดเนียลดับบลิว

-4

ฉันไม่เห็นกรณีการใช้งานจริง ๆ ... ถ้าคุณจะพิมพ์ print_var_name ($ foobar) มีอะไรที่ยากมาก (และแตกต่าง) ในการพิมพ์การพิมพ์ ("foobar") แทน?

เพราะแม้ว่าคุณจะใช้สิ่งนี้ในฟังก์ชั่นคุณก็จะได้ชื่อท้องถิ่นของตัวแปร ...

ในกรณีใด ๆ นี่คือคู่มือการสะท้อนในกรณีที่มีบางสิ่งที่คุณต้องการ


พิมพ์ ("foobar") จะไม่จัดการ vars อื่น ๆ
Gary Willoughby

7
กรณีการใช้งาน: คุณมีจุดแก้จุดบกพร่องน้อยในรหัสกลับมาทิ้งค่าเดียวกัน คุณจะรู้ได้อย่างไรว่าอันไหนที่ถูกประหารชีวิตก่อน? การพิมพ์ฉลากมีประโยชน์มากแล้ว
takeshin

ถ้าอย่างนั้นคุณก็ไม่ได้เขียนโปรแกรมให้เพียงพอ ภาษาส่วนใหญ่ที่ฉันเจอมีวิธีการทำเช่นนี้มักจะง่าย
b01

@ b01 ฉันได้ทำมากมาย ฉันรู้ดีว่ามีหลายภาษาที่อนุญาตสิ่งนี้ แต่สิ่งนั้นไม่ได้มีความหมายมากนัก หลายภาษาเสนอวิธีที่จะข้ามไปได้อย่างง่ายดายและนั่นไม่ได้หมายความว่าคุณควรใช้เพื่อหลีกเลี่ยงการเขียนการควบคุมการไหลที่เหมาะสม นี่เป็นกรณีที่คล้ายกันในมุมมองของฉัน ฉันไม่สงสัยเลยว่ามีกรณีที่สมเหตุสมผลและนั่นเป็นสาเหตุที่ฉันสงสัยเกี่ยวกับกรณีการใช้ที่เหมาะสม
Vinko Vrsalovic
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.