2009-08-06 16 views
8

PHP में निम्नलिखित को देखते हुए:PHP में कंटेनर ऑब्जेक्ट की विधि का संदर्भ लें?

<?php 
class foo { 
    public $bar; 
    function __construct() { 
    "Foo Exists!"; 
    } 

    function magic_bullet($id) { 
    switch($id) { 
    case 1: 
     echo "There is no spoon! "; 
    case 2: 
     echo "Or is there... "; 
     break; 
    } 
    } 
} 

class bar { 
    function __construct() { 
    echo "Bar exists"; 
    } 
    function target($id) { 
    echo "I want a magic bullet for this ID!"; 
    } 
} 

$test = new foo(); 
$test->bar = new bar(); 
$test->bar->target(42); 

मैं अगर यह संभव है 'बार' क्लास 'जादुई गोली' 'foo' वर्ग की विधि कॉल करने के लिए सोच रहा हूँ। 'बार' उदाहरण 'foo' उदाहरण द्वारा निहित है, लेकिन इसके साथ माता-पिता/बाल संबंध में नहीं है। वास्तविकता में, मेरे पास कई अलग-अलग "बार" वर्ग हैं जो "foo" एक सरणी में हैं, प्रत्येक एक अंतिम परिणाम के लिए "magic_bullet" फ़ंक्शन को पास करने के इच्छुक होने से पहले $ आईडी से कुछ अलग कर रहा है, इसलिए संरचना को छोड़कर वर्ग संबंधों में परिवर्तन, क्या 'कंटेनर' उदाहरण की विधि तक पहुंच बनाना संभव है?

उत्तर

4

आपको रिश्ते प्रदान करने के लिए अपने कोड को संशोधित करना होगा। ओओपी-बोल में, हम इसे aggregation पर कॉल करते हैं।

मान लिया जाये कि PHP 4, और "सलाखों की एक सरणी" (हालांकि केवल कोड आप दिखाया है के आधार पर!)

<?php 

class foo { 
    var $bars = array(); 
    function __construct() { 
    "Foo Exists!"; 
    } 

    function magic_bullet($id) { 
    switch($id) { 
    case 1: 
     echo "There is no spoon! "; 
    case 2: 
     echo "Or is there... "; 
     break; 
    } 
    } 

    function addBar(&$bar) 
    { 
    $bar->setFoo($this); 
    $this->bars[] = &$bar; 
    } 
} 

class bar { 
    var $foo; 
    function __construct() { 
    echo "Bar exists"; 
    } 

    function target($id){ 
    if (isset($this->foo)) 
    { 
     echo $this->foo->magic_bullet($id); 
    } else { 
     trigger_error('There is no foo!', E_USER_ERROR); 
    } 
    } 
    function setFoo(&$foo) 
    { 
    $this->foo = &$foo; 
    } 
} 

$test = new foo(); 
$bar1 = new bar(); 
$bar2 = new bar(); 

$test->addBar($bar1); 
$test->addBar($bar2); 

$bar1->target(1); 
$bar1->target(2); 
+0

शानदार! यह बार सेटअप के लिए foo उदाहरण में पॉइंटर जोड़ने के लिए अन्य सुझावों के ऊपर, मेरे सेटअप के लिए काम करता है, क्योंकि कई 'बार' उदाहरणों को मानते हुए, मैं बार उदाहरण के अंदर foo इंस्टेंस की प्रतियां नहीं चाहता (अतिरिक्त मेमोरी उपयोग, प्लस यदि मूल $ परीक्षण उदाहरण कुछ बदलता है जो 'magic_bullet' के व्यवहार को संशोधित करता है, तो सभी प्रतियां पुरानी हो जाएंगी), मुझे एक संदर्भ ('$ this-> pointer_to_foo = &$foo;',' $-- pointer_to_foo = $ foo नहीं चाहिए ')। – MidnightLightning

+0

ध्यान दें कि आप PHP5 के साथ काम कर रहे हैं (आप हैं, यदि __construct का उपयोग कन्स्ट्रक्टर के रूप में करते हैं), तो हस्ताक्षर की कोई आवश्यकता नहीं होनी चाहिए: डिफ़ॉल्ट –

+0

हाहा द्वारा संदर्भ द्वारा ऑब्जेक्ट पास किए जाते हैं, मुझे नहीं पता कि मैं PHP 5 शैली को कैसे चूक गया रचनाकार, मैंने बस 'var' के उपयोग और विधियों पर पहुंच/दृश्यता संशोधक की कमी की कुंजी बंद कर दी। @MidnightLightning यदि आप वास्तव में PHP 5 का उपयोग कर रहे हैं, पास्कल मार्टिन सही है - आपको संदर्भ ऑपरेटर की आवश्यकता नहीं है। मैंने बनाए गए किसी भी भ्रम के लिए खेद है। –

0

आप $bar उदाहरण के लिए, फू के अंदर, यह जानने का कोई तरीका नहीं है कि इसमें कक्षा क्या है; तो, उस के किसी भी तरीके को कॉल करने का कोई तरीका नहीं है।

(ठीक है, शायद प्रतिबिंब के साथ काम कर (शायद नहीं) ... मुझे लगता है कि एक दिन की कोशिश करनी चाहिए, ^^)

संपादित करें: इसके बारे में थोड़ा सोच: आप कर सकते थे, अपने वर्ग के भीतर बार, फू को एक सूचक रखें; इस तरह एक सा:

class foo { 
    var $bar; 
    function __construct() { 
    var_dump("Foo Exists!"); 
    } 

    function magic_bullet($id) { 
     var_dump('magic_bullet : ' . $id); 
    switch($id) { 
    case 1: 
     var_dump("There is no spoon! "); 
    case 2: 
     var_dump("Or is there... "); 
     break; 
    } 
    } 
} 

class bar { 
    protected $pointer_to_foo; 
    function __construct($pointer_to_foo) { 
    var_dump("Bar exists"); 
    $this->pointer_to_foo = $pointer_to_foo; 
    } 
    function target($id) { 
    var_dump("I want a magic bullet for this ID!"); 
    if (method_exists($this->pointer_to_foo, 'magic_bullet')) { 
     $this->pointer_to_foo->magic_bullet($id); 
    } 
    } 
} 

$test = new foo(); 
$test->bar = new bar($test); 
$test->bar->target(42); 

सूचना मैं एक सुरक्षा उपाय के रूप method_exists इस्तेमाल किया।

और आप प्राप्त करेंगे:

string 'Foo Exists!' (length=11) 

string 'Bar exists' (length=10) 

string 'I want a magic bullet for this ID!' (length=34) 

string 'magic_bullet : 42' (length=17) 

इसलिए, यह किया जा सकता है ... आप अपने कोड थोड़ा ;-)


संपादित 2 संशोधित करते हैं: हो, zombat हरा मुझे यह करने के लिए, ऐसा लगता है

4

:-(नहीं, यह संभव नहीं है, क्योंकि वहां कोई संबंध को परिभाषित किया।

मैं सुझाव दूंगा कि $test->bar संपत्ति सीधे सेट करने के बजाय, आप एक सेटर का उपयोग करते हैं, और आप इस तरह से एक रिश्ता स्थापित कर सकते हैं। आपको संपत्ति bar कक्षा में भी जोड़ने की आवश्यकता होगी। अंदर वर्ग foo:

function setBar(bar $bar) 
{ 
    $bar->container = $this; 
    $this->bar = $bar; 
} 

कि वस्तुओं के बीच एक रिश्ता सेट करता है। अब बदलने के लिए bar::target($id) समारोह:

function target($id) 
{ 
    $this->container->magic_bullet($id); 
} 

अब आप यह करने के लिए सक्षम होना चाहिए:

$test = new foo(); 
$bar = new bar(); 
$test->setBar($bar); 
$test->bar->target(42); 
0

आप कुछ विकल्प यहाँ है। मैं वैश्विक मार्ग पर जाने के खिलाफ सिफारिश करता हूं।

 
$test->bar = new bar($test); 

यदि आप बार के कन्स्ट्रक्टर में $ परीक्षण स्टोर करते हैं तो यह काम करेगा। आप यह भी कर सकते हैं:

 
class test { 
... 
    public function target($someInt) { 
    $this->bar->target($someInt,$this); 
    } 
} 
$test->target(42); 

... और बार के लक्ष्य() विधि में दिए गए परीक्षण ऑब्जेक्ट का उपयोग करें।

1

यह मेरे लिए लग रहा है विचार एक स्थिर के लिए एक आदर्श मामला है शायद एक सिंगलटन डिजाइन पैटर्न - विधि ...

<?php 
class foo { 
    var $bar; 
    function __construct() { 
    "Foo Exists!"; 
    } 

    static function magic_bullet($id) { 
    switch($id) { 
    case 1: 
     echo "There is no spoon! "; 
    case 2: 
     echo "Or is there... "; 
     break; 
    } 
    } 
} 

class bar { 
    function __construct() { 
    echo "Bar exists"; 
    } 
    function target($id) { 
    echo Foo::magic_bullet($id) 
    } 
} 

$test = new foo(); 
$test->bar = new bar(); 
$test->bar->target(42); 

या, हो, तो ही कभी एक "फू" ऑब्जेक्ट होने जा रहा?

+0

उत्कृष्ट! हां, मैंने जो कुछ दिया है, उसके आधार पर, एक स्टेटिक विधि या सिंगलटन के साथ जाने से 'जादू_बुललेट' हर किसी के लिए दृश्यमान हो जाएगा। लेकिन वास्तविकता में, एक से अधिक फ़ंक्शन हैं जो 'foo' में है कि मैं 'बार' तक पहुंच प्राप्त करना चाहता हूं, और उन सभी को स्थैतिक बनाने के बजाय, मैं एक अन्य उत्तर – MidnightLightning

+0

से पॉइंटर समाधान के साथ जाऊंगा यदि चीजें इसे सलाखों तक पहुंच की आवश्यकता नहीं है ... फिर एक सिंगलटन सबसे अच्छा विचार हो सकता है। फिर आप Foo :: getInstance() -> any_of_your_functions ($ vars) जैसे कुछ करेंगे; – Mez

संबंधित मुद्दे