2011-01-27 8 views
23

क्या यह निर्धारित करने के लिए PHP में कोई तरीका है कि कोई दिया गया चर किसी अन्य चर के संदर्भ में है और/या किसी अन्य चर द्वारा संदर्भित है? मैं सराहना करता हूं कि comment को को 0pपर सेट करने का अर्थ है "$ ए और $ बी पूरी तरह से बराबर हैं। $ ए $ 1 को इंगित नहीं कर रहा है," संदर्भ "और" संदर्भ से "का पता लगाने के लिए संभव नहीं हो सकता है। बी या इसके विपरीत। $ ए और $ बी एक ही स्थान पर इशारा कर रहे हैं। "यह पता लगाने के लिए कि क्या PHP चर एक संदर्भ/संदर्भित है

यदि यह निर्धारित करना संभव नहीं है कि कोई दिया गया चर संदर्भ/संदर्भित है, तो यह निर्धारित करने का एक सामान्य तरीका है कि दो चर हैं या नहीं एक दूसरे के संदर्भ? फिर, php.net पर comment ऐसी तुलना करने के लिए एक फ़ंक्शन प्रदान करता है - हालांकि यह एक ऐसा है जिसमें चरों में से एक को संपादित करना और यह देखना है कि अन्य चर समान रूप से प्रभावित होता है या नहीं। यदि संभव हो तो मैं इसे संभवतः ऐसा करने से बचाना चाहूंगा क्योंकि कुछ चर जो मैं सोच रहा हूं वह जादू गेटर्स/सेटर्स का भारी उपयोग करता है।

इस उदाहरण में अनुरोध की पृष्ठभूमि संरचनाओं को विस्तार से देखने में सहायता के लिए एक डिबगिंग फ़ंक्शन लिखना है।

+0

आप देख सकते हैं दो चर एक दूसरे के संदर्भ हैं: 'var_export से आउटपुट को कैप्चर http://stackoverflow.com/a/18110347/632951 – Pacerier

उत्तर

6

आप debug_zval_dump उपयोग कर सकते हैं:

function countRefs(&$var) { 
    ob_start(); 
    debug_zval_dump(&$var); 
    preg_match('~refcount\((\d+)\)~', ob_get_clean(), $matches); 
    return $matches[1] - 4; 
} 

$var = 'A'; 
echo countRefs($var); // 0 

$ref =& $var; 
echo countRefs($var); // 1 

यह हालांकि पीएचपी 5.4 के रूप में अब काम नहीं करेगा के रूप में वे संदर्भ समर्थन से कॉल टाइम पास निकाल दिया है और पूर्व के संस्करणों पर एक E_STRICT स्तर त्रुटि फेंक सकता है।

यदि आप सोचते हैं, उपरोक्त फ़ंक्शन में -4 कहां से आया है: आप मुझे बताएं ... मुझे कोशिश करके यह मिला। मेरी आंखों में यह केवल 3 होना चाहिए (परिवर्तनीय, मेरे फ़ंक्शन में चर, चर zend_debug_zval पर पारित किया गया), लेकिन मैं PHP आंतरिक पर बहुत अच्छा नहीं हूं और ऐसा लगता है कि यह कहीं और कहीं और संदर्भ बनाता है;)

+1

' $ var = 'ए' के ​​लिए काम करता है 1 '$ ref = &$var;' 2 है, फिर ' countRefs ($ var) '3 है और' debug_zval_dump (&$var); '4 – Mchl

+1

@Mchl:' $ reg = & $ var' वाला कोड '5',' 4' नहीं देगा। '4' बिना कोड है संदर्भ खिलाडि़यों। यही कारण है कि मुझे संख्या नहीं मिली है। – NikiC

1

संपादित करें: ऐसा लगता है मैं प्रश्न का उत्तर दिया 'यह संभव दो चर स्मृति में एक ही मूल्य संदर्भित कर रहे हैं, तो जाँच करने के लिए है' वास्तविक प्रश्न पूछा नहीं। : पी


जहां तक ​​'सादे' चर का जवाब उत्तर 'नहीं' है।

जहां तक ​​ऑब्जेक्ट्स जाते हैं - शायद।

सभी ऑब्जेक्ट डिफ़ॉल्ट रूप से संदर्भों से संभाले जाते हैं। इसके अलावा प्रत्येक ऑब्जेक्ट में इसका सीरियल नंबर होता है जिसे आप var_dump() पर देख सकते हैं।

>> class a {}; 
>> $a = new a(); 
>> var_dump($a); 

object(a)#12 (0) { 
} 

आप इस # करने के लिए किसी भी तरह मिल सकता है, तो आप प्रभावी रूप से यह दो चर के लिए तुलना, और अगर वे एक ही वस्तु को इंगित देख सकता था। सवाल यह है कि इस नंबर को कैसे प्राप्त करें। var_export() इसे वापस नहीं करता है। मुझे Reflection कक्षाओं में snything नहीं दिख रहा है जो इसे प्राप्त करेगा।

एक बात यह है कि मेरे दिमाग में आता है उत्पादन बफरिंग + regex उपयोग कर रहा है

+0

($ परिवर्तनीय, TRUE) 'फिर एक मामूली regex संख्या –

+0

@ क्रिस्टोफरसेल-स्टोर्गार्ड पर कब्जा कर लेना चाहिए: जो केवल' print_r() ' – calcinai

1

xdebug_debug_zval() पर एक चोटी लें। अभी, यह वास्तव में जानने का एकमात्र तरीका है कि क्या आप चर के जेवल के बारे में सबकुछ निर्धारित कर सकते हैं।

function isRef($var) { 
    $info = getZvalRefCountInfo($var); 
    return (boolean) $info['is_ref']; 
} 
function getRefCount($var) { 
    $info = getZvalRefCountInfo($var); 
    return $info['refcount']; 
} 
function canCopyOnWrite($var) { 
    $info = getZvalRefCountInfo($var); 
    return $info['is_ref'] == 0; 
} 
function canReferenceWithoutCopy($var) { 
    $info = getZvalRefCountInfo($var); 
    return $info['is_ref'] == 1 || $info['refcount'] == 1; 
} 

function getZvalRefCountInfo($var) { 
    ob_start(); 
    xdebug_debug_zval($var); 
    $info = ob_get_clean(); 
    preg_match('(: \(refcount=(\d+), is_ref=(\d+)\))', $info, $match); 
    return array('refcount' => $match[1], 'is_ref' => $match[2]); 
} 
कुछ नमूना चर के साथ

तो:

$a = 'test'; 
$b = $a; 
$c = $b; 
$d =& $c; 
$e = 'foo'; 

हम परीक्षण कर सकते हैं अगर एक चर एक संदर्भ है:

तो यहाँ सहायक कार्यों के एक जोड़े में कुछ उपयोगी जानकारी निर्धारित करने के लिए कर रहे हैं

isRef('a'); // false 
isRef('c'); // true 
isRef('e'); // false 

हम ज़वाल से जुड़े चर की संख्या प्राप्त कर सकते हैं (जरूरी नहीं कि संदर्भ हो, हो सकता है कॉपी-ऑन-राइट) के लिए:

getRefCount('a'); // 2 
getRefCount('c'); // 2 
getRefCount('e'); // 1 

हम अगर हम कॉपी-ऑन-राइट कर सकते हैं परीक्षण कर सकते हैं (एक स्मृति प्रतिलिपि प्रदर्शन के बिना) प्रतिलिपि:

canCopyOnWrite('a'); // true 
canCopyOnWrite('c'); // false 
canCopyOnWrite('e'); // true 

और यदि हम कर सकते हैं हम परीक्षण कर सकते हैं zval कॉपी किए बिना ही एक संदर्भ:

canReferenceWithoutCopy('a'); // false 
canReferenceWithoutCopy('c'); // true 
canReferenceWithoutCopy('e'); // true 

और अब, हम देख सकते हैं कि कुछ काला जादू के माध्यम से एक वैरिएबल संदर्भ में ही:

function isReferenceOf(&$a, &$b) { 
    if (!isRef('a') || getZvalRefCountInfo('a') != getZvalRefCountInfo('b')) { 
     return false; 
    } 
    $tmp = $a; 
    if (is_object($a) || is_array($a)) { 
     $a = 'test'; 
     $ret = $b === 'test'; 
     $a = $tmp; 
    } else { 
     $a = array(); 
     $ret = $b === array(); 
     $a = $tmp; 
    } 
    return $tmp; 
} 

यह थोड़ा हैकी है क्योंकि हम यह निर्धारित नहीं कर सकते कि अन्य प्रतीक एक ही शब्द (केवल अन्य प्रतीकों संदर्भ) का संदर्भ देते हैं। तो यह मूल रूप से यह देखने के लिए जांच करता है कि $a एक संदर्भ है, और यदि $a और $b दोनों का एक ही रिफाउंट और संदर्भ ध्वज सेट है। फिर, यह जांचने के लिए एक बदलता है कि क्या अन्य परिवर्तन (इंगित करते हैं कि वे एक ही संदर्भ हैं)।

5

पूर्ण काम कर उदाहरण:

function EqualReferences(&$first, &$second){ 
    if($first !== $second){ 
     return false; 
    } 
    $value_of_first = $first; 
    $first = ($first === true) ? false : true; // modify $first 
    $is_ref = ($first === $second); // after modifying $first, $second will not be equal to $first, unless $second and $first points to the same variable. 
    $first = $value_of_first; // unmodify $first 
    return $is_ref; 
} 

$a = array('foo'); 
$b = array('foo'); 
$c = &$a; 
$d = $a; 

var_dump(EqualReferences($a, $b)); // false 
var_dump(EqualReferences($b, $c)); // false 
var_dump(EqualReferences($a, $c)); // true 
var_dump(EqualReferences($a, $d)); // false 
var_dump($a); // unmodified 
var_dump($b); // unmodified 
संबंधित मुद्दे