2010-04-10 10 views
12

मान लीजिए कि यह संभव है, PHP में चेतावनी उत्पन्न किए बिना एक भिन्न कार्य के संदर्भ में कोई तर्क कैसे पारित करेगा? हम फ़ंक्शन कॉल में अब '&' ऑपरेटर का उपयोग नहीं कर सकते हैं, अन्यथा मैं इसे स्वीकार करूंगा (भले ही यह त्रुटि प्रवण होगा, एक कोडर इसे भूल जाना चाहिए)।PHP में संदर्भ द्वारा विविध कार्यों के तर्क कैसे पारित किए जा सकते हैं?

यह प्रेरित है कि यह पुराना MySQLi रैपर वर्ग है जो मैंने पाया (इन दिनों, मैं केवल पीडीओ का उपयोग करता हूं)। रैपर और MySQLi कक्षाओं के बीच एकमात्र अंतर है रैपर FALSE लौटने के बजाय अपवाद फेंकते हैं।

class DBException extends RuntimeException {} 
... 
class MySQLi_throwing extends mysqli { 
    ... 
    function prepare($query) { 
     $stmt = parent::prepare($query); 
     if (!$stmt) { 
      throw new DBException($this->error, $this->errno); 
     } 
     return new MySQLi_stmt_throwing($this, $query, $stmt); 
    } 
} 
// I don't remember why I switched from extension to composition, but 
// it shouldn't matter for this question. 
class MySQLi_stmt_throwing /* extends MySQLi_stmt */ { 
    protected $_link, $_query, $_delegate; 

    public function __construct($link, $query, $prepared) { 
     //parent::__construct($link, $query); 
     $this->_link = $link; 
     $this->_query = $query; 
     $this->_delegate = $prepared; 
    } 
    function bind_param($name, &$var) { 
     return $this->_delegate->bind_param($name, $var); 
    } 
    function __call($name, $args) { 
     //$rslt = call_user_func_array(array($this, 'parent::' . $name), $args); 
     $rslt = call_user_func_array(array($this->_delegate, $name), $args); 
     if (False === $rslt) { 
      throw new DBException($this->_link->error, $this->errno); 
     } 
     return $rslt; 
    } 
} 

कठिनाई ऐसी bind_result आवरण पर जैसे तरीकों बुला में निहित है। निरंतर-धैर्य कार्यों (उदा। bind_param) स्पष्ट रूप से परिभाषित किया जा सकता है, पास-दर-संदर्भ के लिए अनुमति देता है। bind_result, हालांकि, पास-दर-संदर्भ होने के लिए सभी तर्कों की आवश्यकता है। यदि आपको MySQLi_stmt_throwing के उदाहरण पर कॉल करते हैं, तो तर्क मूल्य से पारित होते हैं और बाध्यकारी नहीं लेते हैं।

try { 
    $id = Null; 
    $stmt = $db->prepare('SELECT id FROM tbl WHERE ...'); 
    $stmt->execute() 
    $stmt->bind_result($id); 
    // $id is still null at this point 
    ... 
} catch (DBException $exc) { 
    ... 
} 

चूंकि उपरोक्त कक्षाएं अब उपयोग में नहीं हैं, इसलिए यह प्रश्न केवल जिज्ञासा का विषय है। रैपर वर्गों के लिए वैकल्पिक दृष्टिकोण प्रासंगिक नहीं हैं। Null लेने वाले तर्कों के समूह के साथ एक विधि को परिभाषित करना डिफ़ॉल्ट मान सही नहीं है (क्या होगा यदि आप 20 तर्क परिभाषित करते हैं, लेकिन फ़ंक्शन को 21 के साथ बुलाया जाता है?)। उत्तर MySQL_stmt_throwing के संदर्भ में भी लिखे जाने की आवश्यकता नहीं है; यह एक ठोस उदाहरण प्रदान करने के लिए बस मौजूद है।

+0

ओह ... बस प्रश्न में पाया गया कि यह एक dups: http://stackoverflow.com/questions/1925253/php-variable-length-argument-list-by-reference , हालांकि मैं दूसरे प्रश्न के स्वीकृत उत्तर के लिए नीचे का जवाब पसंद करता हूं। – outis

उत्तर

6

PHP में संदर्भ द्वारा परिवर्तनीय लंबाई तर्क सूचियों को पारित करने का कोई तरीका नहीं है। यह भाषा की मौलिक सीमा है।

, तथापि, array(&$var1, &$var2...) वाक्य रचना के साथ एक वैकल्पिक हल वहाँ है:

<?php 

/** raise all our arguments to the power of 2 */ 
function pow2() { 
     $args = &func_get_arg(0); 

     for ($i = 0; $i< count($args); ++$i) { 
      $args[$i] *= 2; 
     } 
} 


$x = 1; $y = 2; $z = 3; 
pow2(array(&$x, &$y, &$z)); // this is the important line 

echo "$x, $y, $z"; // output "2, 4, 6" 

?> 

Test भी function test($args) घोषित किया जा सकता है, लेकिन मैं वर्णन करने के लिए है कि इस कार्य के func_get_args() परिवार के साथ काम करता है चाहता था। यह array(&$x) है जो चर के संदर्भ में पारित होने का कारण बनता है, फ़ंक्शन हस्ताक्षर नहीं।

समारोह तर्क पर पीएचपी के दस्तावेज़ पर एक टिप्पणी से: http://php.net/manual/en/functions.arguments.php

+0

मुझे पागल कहो, लेकिन क्या आपके 'टेस्ट' विधि के लिए 'pow2' या इसके विपरीत होने का मतलब था? –

+0

@anthony पूर्व, धन्यवाद। – meagar

+0

@मेगर, कोई समस्या नहीं, यहां पर देर हो चुकी है अगर मैं हेलुसिनेट करना शुरू कर दूं। –

8

पीएचपी 5.6 आप कर सकते हैंpass arguments by reference के रूप में एक variadic कार्य करने के लिए। यहाँ the RFC से एक उदाहरण है:

public function prepare($query, &...$params) { 
    $stmt = $this->pdo->prepare($query); 
    foreach ($params as $i => &$param) { 
     $stmt->bindParam($i + 1, $param); 
    } 
    return $stmt; 
} 
संबंधित मुद्दे