2009-12-14 8 views
11

कृपया bellow कोड देखें:PHP [ओओपी] - क्लास कन्स्ट्रक्टर को मैन्युअल रूप से कैसे कॉल करें?

01. class Test { 
02.  public function __construct($param1, $param2, $param3) { 
03.   echo $param1.$param2.$param3; 
04.  } 
05. } 
06. 
07. $params = array('p1','p2','p3'); 
08. 
09. $ob = new Test; 
10. 
11. if(method_exists($ob,'__construct')) { 
12.  call_user_func_array(array($ob,'__construct'),$params); 
13. } 

अब, समस्या निर्माता लाइन 09

में कहा जाता है लेकिन मैं इसे कॉल करना चाहते हैं मैन्युअल लाइन 11-13

पर

क्या यह संभव है? तो फिर कैसे? कोई भी विचार कृपया?

+0

ध्यान दें कि यदि निर्माता के पैरामीटर पारित होते हैं संदर्भ, तो call_user_func_array असफल हो जाएगा !! – Sarfraz

उत्तर

21

ऑब्जेक्ट का निर्माण होने पर निर्माता को कॉल करने से रोकने के लिए संभव नहीं है (आपके कोड में लाइन 9)। यदि आपके पास __construct() विधि में कुछ कार्यक्षमता होती है जो आप निर्माण के बाद तक स्थगित करना चाहते हैं, तो आपको इसे किसी अन्य विधि में ले जाना चाहिए। उस विधि के लिए एक अच्छा नाम init() हो सकता है।

ऐसा क्यों न करें?

class Test { 
    public function __construct($param1, $param2, $param3) { 
     echo $param1.$param2.$param3; 
    } 
} 

$ob = new Test('p1', 'p2', 'p3'); 

संपादित करें: मैंने अभी एक हैकी तरीके के बारे में सोचा है जिसे आप एक कन्स्ट्रक्टर को बुलाए जाने से रोक सकते हैं। आप Test उपclass कर सकते हैं और एक खाली, कुछ भी नहीं कन्स्ट्रक्टर के साथ कन्स्ट्रक्टर ओवरराइड कर सकते हैं।

class SubTest extends Test { 
    public function __construct() { 
     // don't call parent::__construct() 
    } 

    public function init($param1, $param2, $param3) { 
     parent::__construct($param1, $param2, $param3); 
    } 
} 

$ob = new SubTest(); 
$ob->init('p1', 'p2', 'p3'); 

यह मतलब हो सकता है अगर आप कुछ कोड है कि आप किसी कारण से नहीं बदल सकते हैं और एक खराब लिखा निर्माता के कुछ कष्टप्रद व्यवहार के आसपास काम करने की जरूरत है साथ काम कर रहे है।

0

पहली बार अपने वस्तु के निर्माण के लिए और उसके बाद पैरामीटर पास अपने इस तरह की कोशिश कर सकते:

class Test { 
    public function __CONSTRUCT($p1="Bundy", $p2="house", $p3=10) { 
     $this->init($p1, $p2, $p3); 
    } 
    public function init($p1, $p2, $p3) { 
     //setup your object here 
    } 
} 

तो यह वस्तु का निर्माण और

$ob->init($p1, $p2, $p3); 

बाद में कॉल करने के लिए संभव है।

+2

यह काम नहीं करता है क्योंकि PHP विधि ओवरलोडिंग का समर्थन नहीं करता है। यह रणनीति जावा जैसी भाषा में काम करेगी। – Asaph

+0

हाँ, आप सही हैं। मैंने कन्स्ट्रक्टर ओवरलोडिंग को हटा दिया .. ... हाल ही में बहुत अधिक जावा किया – justastefan

+0

ठीक है, अच्छा संपादन लेकिन आपका '$ ob-> init ($ params); 'init()' function की आपकी परिभाषा के अनुरूप नहीं दिखता है जो एक एकल सरणी के बजाय 3 तर्क स्वीकार करता है। बीटीडब्ल्यू: जावा जैसी कोई चीज नहीं है। – Asaph

1

यदि प्रारंभिकरण से तत्कालता को अलग करना सख्ती से एक आवश्यकता नहीं है, तो दो अन्य संभावनाएं हैं: पहला, स्थिर कारखाना विधि।

class Test { 
    public function __construct($param1, $param2, $param3) { 
     echo $param1.$param2.$param3; 
    } 

    public static function CreateTest($param1, $param2, $param3) { 
     return new Test($param1, $param2, $param3); 
    } 
} 

$params = array('p1','p2','p3'); 

if(method_exists($ob,'__construct')) { 
    call_user_func_array(array($ob,'CreateTest'),$params); 
} 

या, आप php 5.3.0 या उच्चतर उपयोग कर रहे हैं, तो आप एक लैम्ब्डा उपयोग कर सकते हैं:

class Test { 
    public function __construct($param1, $param2, $param3) { 
     echo $param1.$param2.$param3; 
    } 
} 

$params = array('p1','p2','p3'); 

$func = function ($arg1, $arg2, $arg3) { 
    return new Test($arg1, $arg2, $arg3); 
} 

if(method_exists($ob,'__construct')) { 
    call_user_func_array($func, $params); 
} 

प्रारंभ विधि असफ़ द्वारा वर्णित महान अगर किसी कारण से आप एक की जरूरत है है तात्कालिक रूप से तात्कालिकता से शुरुआतीकरण को अलग करने के लिए, लेकिन यदि उपर्युक्त उपयोग के मामले का समर्थन करना एक विशेष मामला है, नियमित आवश्यकता नहीं है, तो उपयोगकर्ताओं को दो अलग-अलग चरणों में तत्काल आरंभ करने और आरंभ करने की आवश्यकता के लिए असुविधाजनक हो सकता है।

कारखाना विधि अच्छी है क्योंकि यह आपको प्रारंभिक उदाहरण प्राप्त करने के लिए कॉल करने का एक तरीका देती है। वस्तु को उसी ऑपरेशन में प्रारंभ किया जाता है और तत्काल चालू किया जाता है, हालांकि, यदि आपको दोनों को अलग करने की आवश्यकता है तो यह काम नहीं करेगा।

और आखिरकार, मैं लैम्ब्डा की अनुशंसा करता हूं यदि यह प्रारंभिक तंत्र असामान्य रूप से उपयोग किया जाता है, और आप प्रारंभिकरण या फैक्ट्री विधियों के साथ अपनी कक्षा परिभाषा को अव्यवस्थित नहीं करना चाहते हैं जिसका शायद ही कभी उपयोग किया जाएगा।

9

ध्यान दें कि यदि निर्माता (__construct विधि) संदर्भ द्वारा पारित तर्क, समारोह में शामिल है तो:

call_user_func_array 

एक त्रुटि के साथ विफल हो जाएगा।

मैं आपको प्रतिबिंब वर्ग का उपयोग करने का सुझाव देता हूं; यहाँ कैसे आप ऐसा कर सकते है:

// assuming that class file is already included. 

$refMethod = new ReflectionMethod('class_name_here', '__construct'); 
$params = $refMethod->getParameters(); 

$re_args = array(); 

foreach($params as $key => $param) 
{ 
    if ($param->isPassedByReference()) 
    { 
     $re_args[$key] = &$args[$key]; 
    } 
    else 
    { 
     $re_args[$key] = $args[$key]; 
    } 
} 

$refClass = new ReflectionClass('class_name_here'); 
$class_instance = $refClass->newInstanceArgs((array) $re_args); 
0

पीएचपी में आप w/निर्माता बुला ओ वस्तुओं बना सकते हैं। लेकिन यह किसी ऑब्जेक्ट इंस्टेंस को अन-सीरियलाइज करके नए का उपयोग करके काम नहीं करता है।

कन्स्ट्रक्टर को मैन्युअल रूप से बुलाया जा सकता है।

आम तौर पर इसकी आवश्यकता नहीं है। साथ ही देखें: Loading an object from PHP session, does it call constructor?

<?php 

class Test 
{ 
    public function __construct() 
    { 
     echo '__construct called.',"\n"; 
    } 
} 

function old($class) 
{ 
    return unserialize 
    (
     sprintf 
     (
      'O:%d:"%s":0:{}', 
      strlen($class), 
      $class 
     ) 
    ); 
} 

$test = old('Test'); 
$test->__construct(); 
1

मैं अगर वहाँ eval() विधि का उपयोग कर कुछ सुरक्षा चिंताएं हैं पता नहीं है, लेकिन आप अपने आप को इस तरह एक समारोह कर सकता है:

function CreateObj($className,$params) 
{ 
    $strArgs = '$params['.implode('],$params[',array_keys($params)).']'; 
    eval('$ob = new '.$className.'('.$strArgs.');'); 
    return $ob 
} 

और अब $ ओबी को अब इसके सही मानकों के साथ परिभाषित किया जाना चाहिए, मैंने इसका परीक्षण नहीं किया है और शायद कोड में कोई गलती है, लेकिन आपको विचार मिल रहा है ....

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