मैं फ़ंक्शन कॉल में वैकल्पिक तर्क कैसे छोड़ूंगा?


94

ठीक है मैं पूरी तरह से भूल गया कि PHP में तर्क कैसे छोड़ें।

आइए हम कहते हैं:

function getData($name, $limit = '50', $page = '1') {
    ...
}

मैं इस फ़ंक्शन को कैसे कहूंगा ताकि मध्य पैरामीटर डिफ़ॉल्ट मान (यानी। '50') लेता है?

getData('some name', '', '23');

क्या उपरोक्त सही होगा? मैं यह काम करने के लिए प्राप्त करने के लिए प्रतीत नहीं कर सकते।


1
@ क्या आप के लिए देख रहे हो ठीक है? इसे लागू करने के लिए वर्कअराउंड या क्लास की तरह ... या?
रिज़ियर १२

@ Rizier123 मैं यह देखने के लिए कह रहा हूँ कि क्या PHP का वर्तमान संस्करण स्किपिंग तर्कों का समर्थन करता है (जैसे अन्य भाषाएं करते हैं)। वर्तमान उत्तर पुराने हो सकते हैं। बाउंटी विवरण से: "वर्तमान उत्तर पांच साल पुराने हैं। क्या PHP का वर्तमान संस्करण चीजों को बदलता है?"
चक ले बट

1
@ चक तो जवाब शायद होगा: कि कुछ भी नहीं बदला; वर्कअराउंड / कोड के बिना आपको अपनी कार्यक्षमता नहीं मिलेगी।
रिज़ियर १२

यहाँ सभी उत्तर आपको लगता है कि फ़ंक्शन को नियंत्रित किया जा रहा है। यदि वह फ़ंक्शन किसी लाइब्रेरी या फ्रेमवर्क का हिस्सा है, तो आपके पास तर्क 2 के लिए कुछ निर्दिष्ट करने के अलावा कोई विकल्प नहीं है। यदि आपको तर्क 3 की आवश्यकता है। एकमात्र विकल्प फ़ंक्शन के लिए स्रोत को देखना और डिफ़ॉल्ट मान को दोहराने के लिए है।
स्नैप

इसे छोड़ना संभव नहीं है, लेकिन आप डिफ़ॉल्ट तर्क का उपयोग करके पास कर सकते हैं ReflectionFunction। मैंने एक ही सवाल में उस जवाब को पोस्ट किया ।
डेविड

जवाबों:


55

आपकी पोस्ट सही है।

दुर्भाग्य से, यदि आपको पैरामीटर सूची के बहुत अंत में एक वैकल्पिक पैरामीटर का उपयोग करने की आवश्यकता है, तो आपको उस अंतिम पैरामीटर तक सब कुछ निर्दिष्ट करना होगा। आम तौर पर यदि आप मिक्स-एंड-मैच करना चाहते हैं, तो आप उन्हें डिफ़ॉल्ट मान देते हैं , ''या nullयदि वे डिफ़ॉल्ट मान हैं, तो फ़ंक्शन के अंदर उनका उपयोग न करें।


1
क्या आप एक उदाहरण प्रदान कर सकते हैं?
मैं

2
@ यामे गेटाटा फंक्शन $limit = is_numeric($limit) ? $limit : '50';की शुरुआत में करते हैं
कामाफेदर

40

एक डिफ़ॉल्ट को निर्दिष्ट करने के लिए falseया की तरह एक तर्क को "छोड़" करने का कोई तरीका नहीं है null

चूँकि PHP में कुछ सिंथैटिक शुगर की कमी होती है, जब यह आता है, तो आप अक्सर कुछ इस तरह देखेंगे:

checkbox_field(array(
    'name' => 'some name',
    ....
));

जैसा कि, टिप्पणियों में स्पष्ट रूप से कहा गया है, नाम के तर्कों का अनुकरण करने के लिए सरणियों का उपयोग कर रहा है।

यह परम लचीलापन देता है लेकिन कुछ मामलों में इसकी आवश्यकता नहीं हो सकती है। बहुत कम से कम आप सोच सकते हैं कि आप जो भी सोचते हैं वह तर्क सूची के अंत तक सबसे अधिक अपेक्षित नहीं है।


2
मैं एफडब्ल्यूआईडब्ल्यू नाम के तर्कों का अनुकरण करने के लिए सरणियों का उपयोग करके 'कुछ इस तरह' की पहचान करूंगा। :)
अराजकता

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

तो ऐसे परिदृश्य के लिए सबसे अच्छा अभ्यास क्या होगा?
एडम ग्रांट

39

नहीं, इस तरह तर्कों को छोड़ना संभव नहीं है। यदि आप पैरामीटर सूची के अंत में हैं, तो आप केवल तर्क वितर्क छोड़ सकते हैं ।

इसके लिए एक आधिकारिक प्रस्ताव था: https://wiki.php.net/rfc/skipparams , जिसमें गिरावट आई। प्रस्ताव पृष्ठ इस विषय पर अन्य SO प्रश्नों से जुड़ता है।


फिर PHP फ़ंक्शंस में अधिक / कम मापदंडों के वैकल्पिक कैसे हैं?
मैं

2
PHP में डिफ़ॉल्ट पैरामीटर मानों के लिए समर्थन है। लेकिन उन मापदंडों को सूची के अंत में होना चाहिए।
क्रिस्चियन


2
झटके। मुझे इतना पागल बना देता है। यदि आपको किसी अन्य व्यक्ति की सुविधा पसंद नहीं है, तो उसका उपयोग न करें। इंटरनेट कभी-कभी सबसे खराब होता है।
ली सेक्सन

@LeeSaxon समस्या पठनीयता और सुवाह्यता है। 1) यदि कोई पैरामीटर को छोड़ने का फैसला करता है, और कोई डिबगिंग कोड इस तथ्य को याद करता है, तो बहुत भ्रम होता है। 2) नया कोड पुराने संस्करणों पर काम नहीं कर सकता था, बिना किसी बाधा के। और गलतियों की संभावना बहुत अधिक होगी।
मार्क वाल्श

6

वैकल्पिक तर्क को छोड़ने में सक्षम होने के बारे में कुछ भी नहीं बदला है, हालांकि सही वाक्यविन्यास के लिए और NULL को उन तर्कों के लिए निर्दिष्ट करने में सक्षम होने के लिए जो मैं छोड़ना चाहता हूं, यहां बताया गया है कि मैं यह कैसे करूंगा:

define('DEFAULT_DATA_LIMIT', '50');
define('DEFAULT_DATA_PAGE', '1');

/**
 * getData
 * get a page of data 
 *
 * Parameters:
 *     name - (required) the name of data to obtain
 *     limit - (optional) send NULL to get the default limit: 50
 *     page - (optional) send NULL to get the default page: 1
 * Returns:
 *     a page of data as an array
 */

function getData($name, $limit = NULL, $page = NULL) {
    $limit = ($limit===NULL) ? DEFAULT_DATA_LIMIT : $limit;
    $page = ($page===NULL) ? DEFAULT_DATA_PAGE : $page;
    ...
}

इसे इस प्रकार कहा जा सकता है: getData('some name',NULL,'23');और भविष्य में फ़ंक्शन को कॉल करने वाले को हर बार चूक या उनके लिए घोषित निरंतरता को याद रखने की आवश्यकता नहीं है।


1
आप शायद तुलना करना चाहते हैं ($ सीमा === अशक्त)
roelleor

4

सरल उत्तर है, नहीं । लेकिन तर्कों को फिर से व्यवस्थित करते समय इसे क्यों छोड़ें?

तुम्हारा एक " डिफ़ॉल्ट फ़ंक्शन तर्कों का गलत उपयोग " है और जैसा कि आप इसकी अपेक्षा करते हैं, यह काम नहीं करेगा।

PHP प्रलेखन से एक साइड नोट:

डिफ़ॉल्ट तर्कों का उपयोग करते समय, कोई भी चूक किसी भी गैर-डिफ़ॉल्ट तर्क के दाईं ओर होनी चाहिए; अन्यथा, चीजें अपेक्षा के अनुरूप काम नहीं करेंगी।

निम्नलिखित को धयान मे रखते हुए:

function getData($name, $limit = '50', $page = '1') {
    return "Select * FROM books WHERE name = $name AND page = $page limit $limit";
}

echo getData('some name', '', '23');   // won't work as expected

आउटपुट होगा:

"Select * FROM books WHERE name = some name AND page = 23 limit"

डिफ़ॉल्ट फ़ंक्शन तर्कों का सही उपयोग इस तरह होना चाहिए:

function getData($name, $page = '1', $limit = '50') {
    return "Select * FROM books WHERE name = $name AND page = $page limit $limit";
}

echo getData('some name', '23');  // works as expected

आउटपुट होगा:

"Select * FROM books WHERE name = some name AND page = 23 limit 50"

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

संपादित करें: इसे उन nullलोगों के रूप में सेट करना, जो सुझाव दे रहे हैं कि काम हो सकता है और एक अन्य विकल्प है, लेकिन जो आप चाहते हैं, वह सूट नहीं कर सकता है। यदि यह परिभाषित नहीं है तो यह हमेशा डिफ़ॉल्ट को अशक्त कर देगा।


यह सबसे अच्छा उत्तर है क्योंकि यह स्पष्ट रूप से सचित्र वाक्यविन्यास स्पष्टीकरण प्रदान करता है! धन्यवाद!
ईसाई

2

किसी भी पैरामीटर को छोड़ देने के लिए (आपको) डिफ़ॉल्ट पैरामीटर के साथ जाना होगा, सुरक्षित पक्ष पर होना चाहिए।

(अशक्त के लिए निपटना जहां डिफ़ॉल्ट पैरामीटर '' या समान है या इसके विपरीत आपको परेशानी में डाल देगा ...)


2

जैसा कि ऊपर उल्लेख किया गया है, आप मापदंडों को छोड़ नहीं पाएंगे। मैंने यह उत्तर कुछ परिशिष्ट प्रदान करने के लिए लिखा है, जो एक टिप्पणी में रखने के लिए बहुत बड़ा था।

@ फ्रेंक नोके अपने डिफ़ॉल्ट मापदंडों के साथ फ़ंक्शन को कॉल करने का प्रस्ताव करता है, इसलिए उदाहरण के लिए

function a($b=0, $c=NULL, $d=''){ //...

आपको उपयोग करना चाहिए

$var = a(0, NULL, 'ddd'); 

जो कार्यात्मक रूप से पहले दो ( $bऔर $c) मापदंडों को छोड़ने के समान होगा ।

यह स्पष्ट नहीं है कि कौन से चूक हैं ( 0डिफ़ॉल्ट मान प्रदान करने के लिए टाइप किया गया है, या क्या यह महत्वपूर्ण है?)।

एक खतरा यह भी है कि डिफ़ॉल्ट मान समस्या बाहरी (या अंतर्निहित) फ़ंक्शन से जुड़ी होती है, जब डिफ़ॉल्ट मान फ़ंक्शन (या विधि) लेखक द्वारा बदला जा सकता है। इसलिए यदि आप कार्यक्रम में अपना कॉल नहीं बदलते हैं, तो आप अनजाने में इसका व्यवहार बदल सकते हैं।

कुछ वर्कअराउंड कुछ वैश्विक स्थिरांक को परिभाषित करने के लिए हो सकते हैं, जैसे DEFAULT_A_Bकि "फ़ंक्शन ए के बी पैरामीटर का डिफ़ॉल्ट मान" और "इस तरह" पैरामीटर को छोड़ना होगा:

$var = a(DEFAULT_A_B, DEFAULT_A_C, 'ddd');

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

class MyObjectClass {
  const DEFAULT_A_B = 0;

  function a($b = self::DEFAULT_A_B){
    // method body
  }
} 
$obj = new MyObjectClass();
$var = $obj->a(MyObjectClass::DEFAULT_A_B); //etc.

ध्यान दें कि यह डिफ़ॉल्ट स्थिरांक पूरे कोड में एक बार ठीक से परिभाषित किया गया है (विधि घोषणा में भी कोई मूल्य नहीं है), इसलिए कुछ अप्रत्याशित परिवर्तनों के मामले में, आप हमेशा सही डिफ़ॉल्ट मान के साथ फ़ंक्शन / विधि की आपूर्ति करेंगे।

इस समाधान की स्पष्टता निश्चित रूप से कच्चे डिफ़ॉल्ट मूल्यों (जैसे NULL, 0आदि) की आपूर्ति से बेहतर है जो एक पाठक को कुछ नहीं कहते हैं।

(मैं मानता हूं कि कॉलिंग $var = a(,,'ddd');सबसे अच्छा विकल्प होगा)


2

आप तर्कों को छोड़ नहीं सकते हैं, लेकिन आप सरणी मापदंडों का उपयोग कर सकते हैं और आपको केवल 1 पैरामीटर को परिभाषित करने की आवश्यकता है, जो कि मापदंडों का एक सरणी है।

function myfunction($array_param)
{
    echo $array_param['name'];
    echo $array_param['age'];
    .............
}

और आप जितने भी मापदंडों को जोड़ सकते हैं, आपको उन्हें परिभाषित करने की आवश्यकता नहीं है। जब आप फ़ंक्शन को कॉल करते हैं, तो आप अपने मापदंडों को इस तरह से रखते हैं:

myfunction(array("name" => "Bob","age" => "18", .........));

0

खैर जैसा कि सभी ने पहले ही कहा था, कि आप जो चाहते हैं, वह फ़ंक्शन में किसी भी कोड लाइनों को जोड़े बिना PHP में संभव नहीं होगा।

लेकिन आप अपनी कार्यक्षमता प्राप्त करने के लिए किसी फ़ंक्शन के शीर्ष पर इस कोड को रख सकते हैं:

foreach((new ReflectionFunction(debug_backtrace()[0]["function"]))->getParameters() as $param) {
    if(empty(${$param->getName()}) && $param->isOptional())
        ${$param->getName()} = $param->getDefaultValue();
}

इसलिए मूल रूप से debug_backtrace()मुझे फंक्शन का नाम मिलता है जिसमें यह कोड रखा जाता है, फिर एक नया ReflectionFunctionऑब्जेक्ट और लूप बनाते हैं, हालांकि सभी फ़ंक्शन आर्ग्युमेंट्स।

लूप में मैं केवल यह जांचता हूं कि फ़ंक्शन का तर्क क्या है empty()और तर्क "वैकल्पिक" है (इसका अर्थ है कि इसका डिफ़ॉल्ट मान है)। यदि हां, मैं केवल तर्क के लिए डिफ़ॉल्ट मान प्रदान करता हूं।

Demo


0

शून्य करने के लिए सीमा निर्धारित करें

function getData($name, $limit = null, $page = '1') {
    ...
}

और उस फ़ंक्शन को कॉल करें

getData('some name', null, '23');

यदि आप सीमा तय करना चाहते हैं तो आप एक तर्क के रूप में पारित कर सकते हैं

getData('some name', 50, '23');

0

जैसा कि पहले सलाह दी गई थी , कुछ भी नहीं बदला। हालांकि, कई मानकों (विशेष रूप से वैकल्पिक वाले) से सावधान रहें, कोड गंध का एक मजबूत संकेतक है।

शायद आपका कार्य बहुत अधिक हो रहा है:

// first build context
$dataFetcher->setPage(1);
// $dataFetcher->setPageSize(50); // not used here
// then do the job
$dataFetcher->getData('some name');

कुछ मापदंडों को तार्किक रूप से समूहीकृत किया जा सकता है:

$pagination = new Pagination(1 /*, 50*/);
getData('some name', $pagination);
// Java coders will probably be familiar with this form:
getData('some name', new Pagination(1));

अंतिम उपाय में, आप हमेशा एक तदर्थ पैरामीटर वस्तु का परिचय कर सकते हैं :

$param = new GetDataParameter();
$param->setPage(1);
// $param->setPageSize(50); // not used here
getData($param);

(जो कम औपचारिक पैरामीटर सरणी तकनीक का महिमामंडित संस्करण है )

कभी-कभी, पैरामीटर को वैकल्पिक बनाने का बहुत गलत कारण गलत है। इस उदाहरण में, क्या $pageवास्तव में वैकल्पिक होना चाहिए? क्या कुछ पात्रों को सहेजने से वास्तव में फर्क पड़ता है?

// dubious
// it is not obvious at first sight that a parameterless call to "getData()"
// returns only one page of data
function getData($page = 1);

// this makes more sense
function log($message, $timestamp = null /* current time by default */);

0

यह स्निपेट:

    फ़ंक्शन getData ($ नाम, $ विकल्प) {
       $ डिफ़ॉल्ट = सरणी (
            'सीमा' => 50,
            'पृष्ठ' => 2,
        );
        $ args = array_merge ($ डिफ़ॉल्ट, $ विकल्प);
        print_r ($ args);
    }

    getData ('foo', array ());
    getData ('foo', array ('लिमिट' => 2));
    getData ('foo', array ('limit' => 10, 'पेज' => 10));

जवाब है :

     सरणी
    (
        [सीमा] => ५०
        [पेज] => २
    )
    सरणी
    (
        [सीमा] => २
        [पेज] => २
    )
    सरणी
    (
        [सीमा] => १०
        [पेज] => १०
    )


2
अच्छा लगा। लेकिन थोड़ा स्पष्टीकरण मददगार होगा।
21

अच्छा उत्तर है, लेकिन यदि आप वैकल्पिक पैरामीटर को ommit करना चाहते हैं, तो इसे इस तरह से करें: फ़ंक्शन getData ($ नाम, $ args = array ()) {$ चूक = सरणी ('सीमा': => 50, 'पृष्ठ' => 2) ; $ args = array_merge ($ चूक, $ args); } अब इस फ़ंक्शन को केवल पहले पैरामीटर के साथ इस तरह से कॉल करना संभव है: गेटडाटा ('फू');
इकोसिन

0

क्या यही मुझे करना होगा:

<?php

    function getData($name, $limit = '', $page = '1') {
            $limit = (EMPTY($limit)) ? 50 : $limit;
            $output = "name=$name&limit=$limit&page=$page";
            return $output;
    }

     echo getData('table');

    /* output name=table&limit=50&page=1 */

     echo getData('table',20);

    /* name=table&limit=20&page=1 */

    echo getData('table','',5);

    /* output name=table&limit=50&page=5 */

    function getData2($name, $limit = NULL, $page = '1') {
            $limit = (ISSET($limit)) ? $limit : 50;
            $output = "name=$name&limit=$limit&page=$page";
            return $output;
    }

    echo getData2('table');

    // /* output name=table&limit=50&page=1 */

    echo getData2('table',20);

    /* output name=table&limit=20&page=1 */

    echo getData2('table',NULL,3);

    /* output name=table&limit=50&page=3 */

?>

उम्मीद है कि यह किसी की मदद करेगा


0

यह कई तकनीकी रूप से सक्षम उत्तरों के साथ एक पुराना प्रश्न है, लेकिन यह PHP: ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में आधुनिक डिजाइन पैटर्न में से एक के लिए रोता है। आदिम स्केलर डेटा प्रकारों के संग्रह को इंजेक्ट करने के बजाय, एक "इंजेक्ट-ऑब्जेक्ट" का उपयोग करने पर विचार करें जिसमें फ़ंक्शन द्वारा आवश्यक सभी डेटा शामिल हैं। http://php.net/manual/en/language.types.intro.php

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

हम इंजेक्शन-ऑब्जेक्ट को परिनियोजन से पहले गलतियों को पकड़ने के लिए टाइप-हिंट कर सकते हैं। इस लेख में कुछ साल पहले के कुछ विचारों को संक्षेप में प्रस्तुत किया गया है।

https://www.experts-exchange.com/articles/18409/Using-Named-Parameters-in-PHP-Function-Calls.html


0

मुझे वैकल्पिक मापदंडों के साथ एक कारखाना बनाना था, मेरा काम करने के लिए अशक्त coalescing संचालक का उपयोग करना था:

public static function make(
    string $first_name = null,
    string $last_name = null,
    string $email = null,
    string $subject = null,
    string $message = null
) {
    $first_name = $first_name ?? 'First';
    $last_name  = $last_name ?? 'Last';
    $email      = $email ?? 'foo@bar.com';
    $subject    = $subject ?? 'Some subject';
    $message    = $message ?? 'Some message';
}

उपयोग:

$factory1 = Factory::make('First Name Override');
$factory2 = Factory::make(null, 'Last Name Override');
$factory3 = Factory::make(null, null, null, null 'Message Override');

सबसे सुंदर चीज नहीं है, लेकिन परीक्षणों के लिए कारखानों में उपयोग करने के लिए एक अच्छा पैटर्न हो सकता है।



-2

आप अपने फ़ंक्शन कॉल में मध्य पैरामीटर को छोड़ नहीं सकते हैं। लेकिन, आप इसके साथ काम कर सकते हैं:

function_call('1', '2', '3'); // Pass with parameter.
function_call('1', null, '3'); // Pass without parameter.

समारोह:

function function_call($a, $b='50', $c){
    if(isset($b)){
        echo $b;
    }
    else{
        echo '50';
    }
}

मुझे यकीन नहीं है कि आपके पास नीचे वोट क्यों हैं, $ c के अलावा अन्य को भी डिफ़ॉल्ट मान की आवश्यकता है (आपके पास वैकल्पिक विकल्प के बाद कोई आवश्यक तर्क नहीं हो सकता है)।
फ्रैंक फोर्ट

-2

जैसा @ इब्राहिमलाल ने बताया। उन्हें nullमूल्यों पर स्थापित करने के लिए सबसे अच्छा अभ्यास है । बस जाँच करें कि क्या मूल्य दिया गया है nullजिसमें आप अपने परिभाषित चूक का उपयोग करते हैं।

<?php
define('DEFAULT_LIMIT', 50);
define('DEFAULT_PAGE', 1);

function getData($name, $limit = null, $page = null) {
    $limit = is_null($limit) ? DEFAULT_LIMIT : $limit;
    $page = is_null($page) ? DEFAULT_PAGE : $page;
    ...
}
?>

उम्मीद है की यह मदद करेगा।


आपने बस प्रतिक्रिया दोहराई। बल्कि आप उस पर टिप्पणी या टिप्पणी कर सकते थे।
इब्राहिम लॉयल

-6
getData('some name');

बस उन्हें पास न करें और डिफ़ॉल्ट मान स्वीकार किया जाएगा

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.