2010-04-26 10 views
62

मुझे इस पर कोई लगातार जानकारी नहीं मिल रही है। विभिन्न स्रोत अलग-अलग चीजें कहने लगते हैं और आदरणीय php.net स्वयं ( प्रकट होता है) स्पष्ट रूप से यह बताने के लिए नहीं - हालांकि, मुझे स्वीकार करना होगा, मुझे केवल एक त्वरित रूप दिखाई दे रही थी।क्या PHP5 ऑब्जेक्ट संदर्भ से पास हुए हैं?

मामलों में जहां मैं चारों ओर 'भारी' वस्तुओं गुजर रहा में, मैं संदर्भ द्वारा पारित करने के लिए की जरूरत है, लेकिन मैं लिखते रहें नहीं करना चाहती: अगर मैं बस

के साथ भाग प्राप्त कर सकते हैं

function foo(TypeName& $obj) 

function foo(TypeName $obj) 

तो मानक क्या कहता है?

उत्तर

87

ऑब्जेक्ट संदर्भ द्वारा पारित (और असाइन किए गए) हैं। ऑपरेटर के पते का उपयोग करने की कोई ज़रूरत नहीं है।

जो मैंने लिखा है, वह एक ओवरम्प्लिफिकेशन है, लेकिन आपके उद्देश्यों के अनुरूप होगा। documentation कहता है:

PHP5 OOP की कुंजी-अंक से एक है कि अक्सर उल्लेख किया है "वस्तुओं डिफ़ॉल्ट रूप से संदर्भ द्वारा पारित कर रहे हैं" है। यह पूरी तरह से सच नहीं है। यह अनुभाग कुछ उदाहरणों का उपयोग करते हुए सामान्य विचार को संशोधित करता है।

एक PHP संदर्भ एक उपनाम है, जो दो अलग-अलग चर को समान मान पर लिखने की अनुमति देता है। PHP5 के रूप में, किसी ऑब्जेक्ट चर में ऑब्जेक्ट स्वयं मूल्य के रूप में नहीं है। यह केवल एक वस्तु पहचानकर्ता जो वस्तु accessors वास्तविक वस्तु को खोजने के लिए अनुमति देता है शामिल हैं। जब कोई ऑब्जेक्ट तर्क द्वारा भेजा जाता है, तो को किसी अन्य चर पर लौटा या असाइन किया गया है, अलग-अलग चर उपनाम नहीं हैं: वे पहचानकर्ता की प्रतिलिपि रखते हैं, जो को उसी ऑब्जेक्ट पर इंगित करता है।

अधिक विस्तृत स्पष्टीकरण के लिए (oversimplification के साथ-साथ पहचानकर्ताओं को बताता है) this answer देखें।

+1

इस प्रकार आप एक वस्तु indentifier के संदर्भ पारित कर सकते हैं? –

+8

जब आप कोई ऑब्जेक्ट पास करते हैं, तब भी आप "मूल्य से" गुजर रहे हैं। हालांकि, "मूल्य" ऑब्जेक्ट स्वयं नहीं है। मान वस्तु पहचानकर्ता है, जो ऑब्जेक्ट खोजने के लिए एक्सेसर्स (->) का उपयोग करता है। इसलिए जब भी आप किसी ऑब्जेक्ट को पास करते हैं या ऑब्जेक्ट को किसी अन्य चीज़ पर असाइन करते हैं, तो यह संदर्भ से गुजरने जैसा "महसूस करता है"। इसका उपयोग करते समय यह उपनाम की तरह "महसूस करता है" ->। लेकिन तकनीकी रूप से यह उपनाम नहीं है, लेकिन एक मान की एक प्रति जहां मूल्य ऑब्जेक्ट पहचानकर्ता है। यदि यह उपनाम था, तो पूरी तरह से अलग मूल्य पर पुन: असाइन करने से सभी उपनामों को उस नए मूल्य में बदल दिया जाएगा, लेकिन आप देखेंगे कि यह उन्हें उपनाम नहीं बनाता है। – OCDev

+0

@OCDev तो हर बार ऑब्जेक्ट क्लोन हो जाता है? किंडा संसाधन बर्बाद कर रहा है। –

3

PHP 5 के अनुसार, सभी ऑब्जेक्ट पास किए जाते हैं और संदर्भ द्वारा असाइन किए जाते हैं।

पीएचपी 4 में, आप अभी भी निर्दिष्ट करने के लिए, जहाँ आप संदर्भ द्वारा पारित वस्तुओं चाहते हैं, स्पष्ट रूप से & ऑपरेटर का उपयोग करके की जरूरत है।

8
PHP manual से

:

तुम इतनी समारोह चर संशोधित कर सकते हैं एक समारोह के संदर्भ द्वारा एक चर पारित कर सकते हैं। वाक्य रचना के रूप में इस प्रकार है:

<?php 
function foo(&$var) 
{ 
    $var++; 
} 

$a=5; 
foo($a); 
// $a is 6 here 
?> 

नोट: वहाँ एक समारोह फोन पर कोई संदर्भ संकेत है - केवल समारोह परिभाषा पर। फंक्शन परिभाषा अकेले संदर्भ के अनुसार तर्क को सही ढंग से पास करने के लिए पर्याप्त हैं। PHP 5.3 के रूप में।0, आपको चेतावनी मिलेगी कि "कॉल-टाइम पास-बाय-रेफरेंस" & foo (& $ ए) में उपयोग करते समय बहिष्कृत किया गया है;

और What's New in PHP5 से:

PHP 5 में, ऑब्जेक्ट मॉडल के बुनियादी ढांचे वस्तु हैंडल के साथ काम करने के लिए लिखा गया था। जब तक आप क्लोन कीवर्ड का उपयोग करके किसी ऑब्जेक्ट को स्पष्ट रूप से क्लोन नहीं करते हैं तो आप कभी भी दृश्य ऑब्जेक्ट्स के दृश्य डुप्लीकेट के पीछे बनाते हैं। PHP 5 में, वहाँ न तो एक संदर्भ

तो इसलिए केवल समय आप function foo(&$var) सिंटैक्स का उपयोग करने की आवश्यकता द्वारा संदर्भ द्वारा वस्तुओं पारित है और न ही उन्हें बताए करने की आवश्यकता है, तो $ वर का एक उदाहरण नहीं हो सकता है एक कक्षा।

+0

मैं आपके कथन में पैडेंटिक अपवाद ले रहा हूं "इसलिए इसलिए आपको केवल << पास द्वारा संदर्भ >> वाक्यविन्यास का उपयोग करने की आवश्यकता है, यदि $ var कक्षा का उदाहरण नहीं हो सकता है"। एक और महत्वपूर्ण स्थिति है जहां आप कक्षा के उदाहरण के लिए उप-संदर्भ का उपयोग करना चाहते हैं ... यदि कोई फ़ंक्शन कॉल करने के परिणामस्वरूप, आप चाहते हैं कि पैरामीटर जिसे आप पास करते हैं (इंगित करें) एक * अलग * उदाहरण, तो आपको संदर्भ द्वारा पारित पैरामीटर लेने के लिए फ़ंक्शन की आवश्यकता होगी, और फ़ंक्शन में आप उस पैरामीटर को एक अलग उदाहरण में असाइन करेंगे। –

1

हाँ PHP5 से हां, ऑब्जेक्ट संदर्भ द्वारा पारित किए जाते हैं। स्पष्ट रूप से ऐसा करने की आवश्यकता नहीं है।

http://www.php.net/manual/en/migration5.oop.php

PHP 5 में एक नया ऑब्जेक्ट मॉडल है। ऑब्जेक्ट्स के PHP की हैंडलिंग पूरी तरह से फिर से लिखी गई है, जिससे बेहतर प्रदर्शन और अधिक सुविधाएं मिलती हैं। PHP के पिछले संस्करणों में, वस्तुओं को आदिम प्रकारों (उदाहरण के लिए पूर्णांक और तार) के रूप में संभाला गया था। इस विधि की कमी यह थी कि जब एक चर को असाइन किया गया था, या विधि के पैरामीटर के रूप में पारित किया गया था, तो पूरी तरह से ऑब्जेक्ट की प्रतिलिपि बनाई गई थी। नए दृष्टिकोण में, वस्तुओं को हैंडल द्वारा संदर्भित किया जाता है, न कि मूल्य से (कोई एक वस्तु के पहचानकर्ता के रूप में हैंडल के बारे में सोच सकता है)।

2

संक्षिप्त उत्तर हाँ है। Objects and references से:

PHP5 OOP की कुंजी-अंक में से एक अक्सर उल्लेख किया है "वस्तुओं डिफ़ॉल्ट रूप से संदर्भ द्वारा पारित कर रहे हैं" कि है। यह पूरी तरह से सच नहीं है। यह अनुभाग कुछ उदाहरणों का उपयोग करते हुए सामान्य विचार को संशोधित करता है।

एक PHP संदर्भ एक उपनाम है, जो दो अलग-अलग चर को समान मान पर लिखने की अनुमति देता है। PHP5 के रूप में, किसी ऑब्जेक्ट चर में ऑब्जेक्ट स्वयं मूल्य के रूप में नहीं है। यह केवल एक वस्तु पहचानकर्ता जो वस्तु accessors वास्तविक वस्तु को खोजने के लिए अनुमति देता है शामिल हैं। जब कोई ऑब्जेक्ट तर्क द्वारा भेजा जाता है, तो को किसी अन्य चर पर लौटा या असाइन किया गया है, अलग-अलग चर उपनाम नहीं हैं: वे पहचानकर्ता की प्रतिलिपि रखते हैं, जो को उसी ऑब्जेक्ट पर इंगित करता है।

क्या मायने रखती है कि, ऐसा होता है कि आप चिंता में, आप एक वस्तु की एक प्रति बनाने कभी नहीं होगा जब तक आप स्पष्ट समारोह कॉल में क्लोन कीवर्ड का उपयोग है। चाहे वह उपनाम है या पहचानकर्ता इस तथ्य को नहीं बदलता है।

+0

आगे स्पष्टीकरण के लिए, एक उदाहरण है कि मेरे पास एक पीएसआर -7 प्रतिक्रिया ऑब्जेक्ट है जो 'functionName (\ Response $ प्रतिक्रिया)' के रूप में पारित होता है, जैसे मैं PHP 5+ में इस 'functionName (\ Response & $ प्रतिक्रिया)' लिख रहा हूं? जब यह सच होता है तो मुझे अपनी छोटी परियोजना में सब कुछ फिर से सोचना होगा। –

+1

@ ZsoltOroszlany में [पीएसआर -7] (http://www.php-fig.org/psr/psr-7/), प्रतिक्रियाओं को परिभाषा द्वारा अपरिवर्तनीय होने की आवश्यकता है। इसका मतलब है कि कार्यान्वयन को 'क्लोन' को स्पष्ट रूप से कॉल करना होगा, उदाहरण के लिए [स्लिम फ्रेमवर्क] (https://github.com/slimphp/Slim/blob/3.7.0/Slim/Http/Response.php#L182)। –

4

यह थोड़ा और सटीक प्रतीत होता है, किसी ऑब्जेक्ट का मान मान द्वारा पारित किया जाता है, लेकिन किसी ऑब्जेक्ट का मान एक पॉइंटर होता है। यह सिर्फ एक संदर्भ पारित करने से अलग है।

http://www.php.net/manual/en/language.oop5.references.php पर सूचीबद्ध उदाहरण अच्छा है। पहले सेट में, $ ए = न्यूल; $ b को प्रभावित नहीं करता है क्योंकि $ केवल एक सूचक था। दूसरे सेट में, $ सी = न्यूल; $ डी को न्यूल होने का कारण बनता है क्योंकि $ d $ c का संदर्भ है।

<?php 
class A { 
    public $foo = 1; 
} 

$a = new A; 
$b = $a; 
$a->foo = 2; 
$a = NULL; 
echo $b->foo."\n"; // 2 

$c = new A; 
$d = &$c; 
$c->foo = 2; 
$c = NULL; 
echo $d->foo."\n"; // Notice: Trying to get property of non-object... 
?> 
1

बस एक उदाहरण है जहां गुजर "वस्तुओं" संदर्भ द्वारा उपयोगी है:

class RefTest1 
{ 
    public $foo; 

    public function __construct(RefTest2 &$ref = null) 
    { 
     $this->foo =& $ref; 
    } 
} 

class RefTest2 
{ 
    public $foo; 

    public function __construct(RefTest1 &$ref = null) 
    { 
     $this->foo =& $ref; 
    } 
} 

class RefTest3 
{ 
    public $foo; 

    public function __construct(RefTest2 &$ref = null) 
    { 
     $this->foo =& $ref; 
    } 
} 

class DoCrossRef 
{ 
    public $refTest1; 
    public $refTest2; 

    public function __construct() 
    { 
     $this->refTest1 = new RefTest1($this->refTest2); 
     $this->refTest2 = new RefTest2($this->refTest1); 
    } 

    public function changeReference() 
    { 
     $this->refTest1 = new RefTest3($this->refTest2); 
    } 
} 

अंत RefTest1 पर RefTest2 के लिए एक संदर्भ और दूसरी तरह के आसपास रखती है, यह भी पूछेंगे कि RefTest2 वस्तु अस्तित्व में नहीं था उस समय RefTest1 बनाया गया था।

DoCrossRef->changeReference() पर कॉल करने के बाद, RefTest2 ऑब्जेक्ट्स में भी RefTest3 ऑब्जेक्ट का संदर्भ है।

0

यहां एक और उदाहरण है कि यह पुष्टि करता है कि वस्तुएं संदर्भ द्वारा पारित की जाती हैं।

<?php 

// discussion: https://stackoverflow.com/questions/2715026/are-php5-objects-passed-by-reference#_=_ 
class A { 
    public $foo = 1; 
} 

class B { 
    function inc($obj) { 
     $obj->foo++; 
    } 
} 

$objA = new A(); 
$objB = new B(); 
$objB->inc($objA); 

echo "[" . $objA->foo . "]"; // Outputs [2] 
संबंधित मुद्दे