2012-06-11 14 views
23

अगर वहाँ कार्यावधि में एक वर्ग के लिए एक नई विधि संलग्न करने के लिए php में, एक रास्ता है मैं सोच रहा हूँ पर वर्ग विधि पैदा करते हैं। मेरा मतलब है, उदाहरण स्तर पर नहीं बल्कि सीधे कक्षा में, ताकि सभी नए बनाए गए उदाहरणों में, यह नई विधि हो। क्या ऐसी चीज प्रतिबिंब के साथ की जा सकती है?php क्रम

धन्यवाद

उत्तर

20

हाँ, आप कर सकते हैं।

नीचे php 5.4.x में रनटाइम में विधि बनाने का तरीका है।

गुमनाम समारोह बंद वर्ग का प्रतिनिधित्व करती है 5.3.x. से शुरू 5.4.x से, यह अज्ञात फ़ंक्शन को किसी विशेष ऑब्जेक्ट या क्लास में बाध्य करने के लिए Closure::bind स्थैतिक विधि जोड़ता है।

उदाहरण:

class Foo { 
    private $methods = array(); 

    public function addBar() { 
     $barFunc = function() { 
     var_dump($this->methods); 
     }; 
     $this->methods['bar'] = \Closure::bind($barFunc, $this, get_class()); 
    } 

    function __call($method, $args) { 
      if(is_callable($this->methods[$method])) 
      { 
      return call_user_func_array($this->methods[$method], $args); 
      } 
    } 
} 

$foo = new Foo; 
$foo->addBar(); 
$foo->bar(); 
+2

बहुत बढ़िया। इस नई PHP फीचर्स को प्यार करें – Thomas

+0

यहां __call विधि का बिंदु क्या है, यदि \ Closure :: बाइंड चीज़ करता है, और इसके विपरीत? – jayarjo

+2

@Jayarjo '\ Closure :: बाइंड 'अज्ञात फ़ंक्शन के संदर्भ को बदलता है (इस मामले में, यह सुनिश्चित करता है कि, बंद होने के भीतर,' $ this' सही ऑब्जेक्ट को संदर्भित करता है)। हालांकि, यह उस कार्य को '$ इस 'की विधि में नहीं बनाता है। बाहरी कोड को बंद करने के लिए अनुमति देने के लिए हमें अभी भी '__call' की आवश्यकता है जैसे कि यह एक विधि थी। –

3

आप डॉक्स में create_function() पर एक नज़र उठाया है? आप वांछित परिणाम भी overloading प्राप्त कर सकते हैं।

+0

create_function (एफएएस के रूप में के रूप में मैं जानता हूँ कि) वैश्विक संदर्भ में काम करता है बनाता है और अधिक भार के रूप में स्वच्छ एक समाधान नहीं है के रूप में मैं यह चाहते हैं – Thomas

+0

मुझे समझ में किया जाना है। PHP, हालांकि, इस परिदृश्य में एक आदर्श गतिशील भाषा के रूप में नहीं है। मेरा मानना ​​है [प्रतिबिंब] (http://www.php.net/manual/en/intro.reflection.php) या [रंकिट] (http://www.php.net/manual/en/intro.runkit.php) एक करीबी समाधान प्राप्त करने के लिए आवश्यक होगा, जिसे आपने अपने प्रश्न में बताया था। –

+0

मुझे प्रतिबिंब के साथ एक समाधान पसंद आएगा, लेकिन मुझे कहीं भी जानकारी का पता लगाना प्रतीत नहीं होता है। एपीआई को देखते हुए ऐसा कुछ भी नहीं है जिसे मैं – Thomas

7

पूरी बात के साथ कुछ खेल के आसपास था। ऐसा लगता है कि ReflectionClass के साथ संभावित रूप से आप जो कुछ भी कर सकते हैं वह मौजूदा विधि को प्रतिस्थापित करना है। लेकिन यह भी अप्रत्यक्ष रूप से होगा।

मैं वास्तव में किसी वर्ग-आधारित भाषा को नहीं जानता, जहां गतिशील वर्ग मौजूद हैं (फिर फिर, मेरा ज्ञान काफी सीमित है)। मैंने इसे प्रोटोटाइप-आधारित भाषाओं (जावास्क्रिप्ट, रूबी, स्मॉलटाक) में ही देखा है। इसके बजाय आप क्या कर सकते, पीएचपी 5.4 में, Closure का उपयोग करें और एक को नए तरीके जोड़ मौजूदा ऑब्जेक्ट है।

class Container 
{ 
    protected $target; 
    protected $className; 
    protected $methods = []; 

    public function __construct($target) 
    { 
     $this->target = $target; 
    } 

    public function attach($name, $method) 
    { 
     if (!$this->className) 
     { 
      $this->className = get_class($this->target); 
     } 
     $binded = Closure::bind($method, $this->target, $this->className); 
     $this->methods[$name] = $binded; 
    } 

    public function __call($name, $arguments) 
    { 
     if (array_key_exists($name, $this->methods)) 
     { 
      return call_user_func_array($this->methods[$name] , $arguments); 
     } 

     if (method_exists($this->target, $name)) 
     { 
      return call_user_func_array( 
       array($this->target, $name), 
       $arguments 
       ); 
     } 
    } 
} 

इस का उपयोग करने के लिए, यदि आप एक मौजूदा वस्तु के साथ निर्माता प्रदान करने के लिए है:

यहां कक्षा जो आप किसी भी वस्तु के लिए इस तरह विकृति प्रदर्शन करते हैं होता है। यहां उपयोग का छोटा उदाहरण दिया गया है:

class Foo 
{ 
    private $bar = 'payload'; 
}; 
$foobar = new Foo; 
// you initial object 


$instance = new Container($foobar); 
$func = function ($param) 
{ 
    return 'Get ' . $this->bar . ' and ' . $param; 
}; 
$instance->attach('test', $func); 
// setting up the whole thing 


echo $instance->test('lorem ipsum'); 
// 'Get payload and lorem ipsum' 

बिल्कुल वही नहीं जो आप चाहते हैं, लेकिन AFAIK यह उतना करीब है जितना आप प्राप्त कर सकते हैं।

3

यह runkit एक्सटेंशन के runkit_method_add() साथ संभव है। हालांकि उत्पादन में इसका उपयोग सावधान रहें।

उदाहरण:

<?php 
class Example {} 

$e = new Example(); 

runkit_method_add(
    'Example', 
    'add', 
    '$num1, $num2', 
    'return $num1 + $num2;', 
    RUNKIT_ACC_PUBLIC 
); 

echo $e->add(12, 4); 
संबंधित मुद्दे