2009-12-18 14 views
19

मैं कन्स्ट्रक्टर को भेजे जाने वाले तर्कों के दिए गए सरणी के साथ कक्षा कैसे बना सकता हूं? की तर्ज पर कुछ:क्या कोई नया वर्ग उदाहरण बनाने के लिए कॉल_user_func() समतुल्य है?

class a { 
    var $args = false; 
    function a() {$this->args = func_get_args();} 
} 

$a = call_user_func_array('new a',array(1,2,3)); 
print_r($a->args); 

आदर्श रूप में यह काम करने के लिए कक्षा में संशोधन के बिना, दोनों PHP4 और PHP5 में की जरूरत है। कोई विचार?

+2

आप ऐसा क्यों करना चाहते हैं? आप कौनसी समस्याएं हल करने की कोशिश कर रहे हैं? – Skilldrick

+0

@ स्किलड्रिक: मेरे मामले में, एक साधारण निर्भरता इंजेक्शन कंटेनर को लागू करने की कोशिश कर रहा है। –

+0

संभावित डुप्लिकेट [PHP में कॉल \ _user \ _func \ _array के साथ कन्स्ट्रक्टर को कैसे कॉल करें] (http://stackoverflow.com/questions/2409237/how-to-call-the-constructor-with-call-user- func-array-in-php) – Maks3w

उत्तर

24

ReflectionClass:newInstance() (या newInstanceArgs()) चलिए आप ऐसा करते हैं।

उदा।

class Foo { 
    public function __construct() { 
    $p = func_get_args(); 
    echo 'Foo::__construct(', join(',', $p), ') invoked'; 
    } 
} 

$rc = new ReflectionClass('Foo'); 
$foo = $rc->newInstanceArgs(array(1,2,3,4,5)); 

संपादित करें: ReflectionClass बिना और शायद संगत PHP4 (क्षमा करें, हाथ में कोई php4 अभी)

class Foo { 
    public function __construct() { 
    $p = func_get_args(); 
    echo 'Foo::__construct(', join(',', $p), ') invoked'; 
    } 
} 

$class = 'Foo'; 
$rc = new $class(1,2,3,4); 

गति तुलना: के बाद से प्रतिबिंब की गति यहाँ उल्लेख किया गया है एक छोटे से (सिंथेटिक) है परीक्षण

define('ITERATIONS', 100000); 

class Foo { 
    protected $something; 
    public function __construct() { 
    $p = func_get_args(); 
    $this->something = 'Foo::__construct('.join(',', $p).')'; 
    } 
} 

$rcStatic=new ReflectionClass('Foo'); 
$fns = array(
    'direct new'=>function() { $obj = new Foo(1,2,3,4); }, 
    'indirect new'=>function() { $class='Foo'; $obj = new $class(1,2,3,4); }, 
    'reflection'=>function() { $rc=new ReflectionClass('Foo'); $obj = $rc->newInstanceArgs(array(1,2,3,4)); }, 
    'reflection cached'=>function() use ($rcStatic) { $obj = $rcStatic->newInstanceArgs(array(1,2,3,4)); }, 
); 


sleep(1); 
foreach($fns as $name=>$f) { 
    $start = microtime(true); 
    for($i=0; $i<ITERATIONS; $i++) { 
    $f(); 
    } 
    $end = microtime(true); 
    echo $name, ': ', $end-$start, "\n"; 
    sleep(1); 
} 

जो मेरे (इतनी तेजी से नहीं) नोटबुक

पर प्रिंट
direct new: 0.71329689025879 
indirect new: 0.75944685935974 
reflection: 1.3510940074921 
reflection cached: 1.0181720256805 

क्या यह बुरा नहीं है, है ना?

+0

ध्यान रखें VolkerK का उत्तर केवल PHP5 – Mark

+0

में उपलब्ध है प्रतिबिंब केवल PHP5 में समर्थित है, लेकिन यह वही तरीका है जो मैं करूँगा। –

+0

मैं उत्पादन कोड में किसी भी प्रतिबिंब का उपयोग करने के खिलाफ सिफारिश करेंगे। यह बहुत धीमा है। –

9

Factory Method pattern पर एक नज़र डालें और बाहर की जाँच this example

विकिपीडिया से:

कारखाने विधि पैटर्न एक वस्तु उन्मुख डिजाइन पैटर्न है। अन्य रचनात्मक पैटर्न की तरह, यह को (उत्पादों) बनाने की समस्या के साथ ऑब्जेक्ट की सटीक कक्षा निर्दिष्ट किए बिना बनाया गया है।

यदि आप इसके लिए एक समर्पित फैक्टरी का उपयोग नहीं करना चाहते हैं, तो आप अभी भी wrap Volker's code फ़ंक्शन में कर सकते हैं, उदा।

/** 
* Creates a new object instance 
* 
* This method creates a new object instance from from the passed $className 
* and $arguments. The second param $arguments is optional. 
* 
* @param String $className class to instantiate 
* @param Array $arguments arguments required by $className's constructor 
* @return Mixed instance of $className 
*/ 
function createInstance($className, array $arguments = array()) 
{ 
    if(class_exists($className)) { 
     return call_user_func_array(array(
      new ReflectionClass($className), 'newInstance'), 
      $arguments); 
    } 
    return false; 
} 
संबंधित मुद्दे