পিএইচপি ফাংশন ওভারলোডিং


195

সি ++ ব্যাকগ্রাউন্ড থেকে আসছে;)
কীভাবে আমি পিএইচপি ফাংশনগুলি ওভারলোড করতে পারি?

একটি যুক্তি আছে যদি একটি ফাংশন সংজ্ঞা, এবং অন্য কোন আর্গুমেন্ট আছে? এটি কি পিএইচপি সম্ভব? বা G _GET এবং পোষ্ট থেকে কোন প্যারামিটার পাস হয়েছে কিনা তা পরীক্ষা করার জন্য আমার অন্যটি ব্যবহার করা উচিত ?? এবং তাদের সম্পর্কিত?


1
আপনি কেবল ক্লাসের পদ্ধতিগুলি ওভারলোড করতে পারেন তবে কার্যকরী নয়। Php.net/manual/en/language.oop5.overloading.php
স্পেশাল

1
আপনি একটি ফাংশন তৈরি করতে পারেন যা আর্গুমেন্টের সংখ্যা পরিষ্কারভাবে পরীক্ষা করে এবং এর একটি পূর্বনির্ধারিত সেট থেকে অন্য ফাংশন সম্পাদন করে। যাইহোক আপনি নিজের সমাধানটি আরও ভালভাবে ডিজাইন করতে চেয়েছিলেন, বা আপনার ইন্টারফেস প্রয়োগকারী ক্লাস ব্যবহার করুন
কলিপ্টো

2
যেমন php.net/manual/en/language.oop5.overloading.php বলেছেন, পিএইচপি-র ওভারলোডিংয়ের সংজ্ঞা টিওপিকাল ওওপি ভাষার চেয়ে আলাদা। তারা কেবল ম্যাজিক পদ্ধতিগুলি উল্লেখ করে যা এক্স এর উপর ভিত্তি করে বৈশিষ্ট্য এবং ফাংশনগুলির গতিশীল রাউটিংয়ের অনুমতি দেয়
এডউইন ড্যানিয়েল

ভবিষ্যতের পাঠকদের জন্য: @ স্পেচাল যা উল্লেখ করছেন, overloadingপ্রশ্নে জিজ্ঞাসা করার চেয়ে শব্দের আলাদা অর্থ । (আরও তথ্যের জন্য স্বীকৃত উত্তর দেখুন))
টুলমেকারস্টেভ

2
পিএইচপি 7 এর পরে কিছু পরিবর্তন হয়েছে? : ও
নওফাল

উত্তর:


217

আপনি পিএইচপি ফাংশনগুলি ওভারলোড করতে পারবেন না। ফাংশন স্বাক্ষরগুলি কেবল তাদের নামের উপর ভিত্তি করে এবং যুক্তি তালিকাগুলি অন্তর্ভুক্ত করে না, সুতরাং আপনার একই নামের সাথে দুটি ফাংশন থাকতে পারে না। ক্লাস পদ্ধতি ওভারলোডিং অন্যান্য অনেক ভাষার চেয়ে পিএইচপিতে আলাদা। পিএইচপি একই শব্দ ব্যবহার করে তবে এটি একটি ভিন্ন ধরণের বর্ণনা করে।

আপনি যাইহোক, একটি ভেরিয়েডিক ফাংশন ঘোষণা করতে পারেন যা একটি পরিবর্তনশীল সংখ্যক আর্গুমেন্ট গ্রহণ করে। আপনি ব্যবহার করতে পারেন func_num_args()এবং func_get_arg()তর্কগুলি পাস করার জন্য, এবং এগুলি সাধারণভাবে ব্যবহার করুন।

উদাহরণ স্বরূপ:

function myFunc() {
    for ($i = 0; $i < func_num_args(); $i++) {
        printf("Argument %d: %s\n", $i, func_get_arg($i));
    }
}

/*
Argument 0: a
Argument 1: 2
Argument 2: 3.5
*/
myFunc('a', 2, 3.5);

8
হতে পারে আমি সি ++ বেশি বিকাশ করছি, তবে আমি একটি ইঙ্গিত বলতে চাই যে এটি ফাংশন পরামিতিগুলির মতো করা হচ্ছে myFunc(/*...*/)
দাগ 65536

4
@ ডগ 65536, পিএইচপি 5.6+ আমাদের "মহান" ত্রাণের জন্য সিনট্যাক্স টোকেন হিসাবে "..." সমর্থন করবে । ;)
এসজেড

অথবা আদিলের উত্তরটি দেখুন , যা সি ++ এর ওভারলোডিংয়ের কাছাকাছি - পিএইচপির মতো আলগাভাবে টাইপ করা ভাষায় যেমন পাওয়া সম্ভব তত কাছাকাছি। এটি পিএইচপি 7-তে আরও বেশি উপযুক্ত, কারণ আপনি প্যারামিটারগুলির জন্য টাইপ ইঙ্গিতগুলি সরবরাহ করতে পারেন, যদি আপনার সমস্ত ওভারলোডগুলিতে তারা একই ধরণের হয়।
টুলমেকারস্টেভ

78

পিএইচপি traditionalতিহ্যবাহী পদ্ধতি ওভারলোডিং সমর্থন করে না, তবে আপনি যা চান তা অর্জন করতে সক্ষম হতে পারে এমন এক উপায় হ'ল __callযাদু পদ্ধতিটি ব্যবহার করা :

class MyClass {
    public function __call($name, $args) {

        switch ($name) {
            case 'funcOne':
                switch (count($args)) {
                    case 1:
                        return call_user_func_array(array($this, 'funcOneWithOneArg'), $args);
                    case 3:
                        return call_user_func_array(array($this, 'funcOneWithThreeArgs'), $args);
                 }
            case 'anotherFunc':
                switch (count($args)) {
                    case 0:
                        return $this->anotherFuncWithNoArgs();
                    case 5:
                        return call_user_func_array(array($this, 'anotherFuncWithMoreArgs'), $args);
                }
        }
    }

    protected function funcOneWithOneArg($a) {

    }

    protected function funcOneWithThreeArgs($a, $b, $c) {

    }

    protected function anotherFuncWithNoArgs() {

    }

    protected function anotherFuncWithMoreArgs($a, $b, $c, $d, $e) {

    }

}

20
আমি এর __call()আগে এর ব্যবহার দেখিনি । বেশ সৃজনশীল (যদি একটু ভার্বোস হয়)! +1 টি
BoltClock

__Call () এর সত্যই প্রশংসনীয় ব্যবহার
অভিষেক গুপ্ত

2
আসলে, এটির সাথে একমত হতে পারে না এবং অবশ্যই এই পরামর্শটি সহকারে অনুশীলন করা উচিত। একটির জন্য, __call () এর এই ব্যবহারটি একটি অ্যান্টি-প্যাটার্ন। দ্বিতীয়ত, সঠিক দৃশ্যমানতা আছে এমন শ্রেণি পদ্ধতিগুলির জন্য পিএইচপি-তে ওভারলোডিং করা সম্ভব। তবে আপনি পারবেন না - প্লেইন জেন ফাংশনগুলি ওভারলোড করুন।
ওডম্যান

1
আপনি __call () ব্যবহারকে একটি অ্যান্টি-প্যাটার্ন বলে কেন ব্যাখ্যা করতে পারেন? পিএইচপি পদ্ধতি ওভারলোডিং ওপি যা খুঁজছে তা নয় - তারা একই নামের সাথে একাধিক পদ্ধতির স্বাক্ষর রাখার দক্ষতা চায় তবে ভিন্ন ইনপুট / আউটপুট: en.wikedia.org/wiki/Function_overloading
স্টিফেন

20
__Call () ব্যবহার করার দরকার নেই। পরিবর্তে কোনও প্যারামিটার তালিকাভুক্ত না করে নিজের নাম রাখার পদ্ধতিটি ঘোষণা করুন এবং উপযুক্ত বেসরকারী প্রয়োগে প্রেরণের জন্য সেই পদ্ধতির মধ্যে func_get_args () ব্যবহার করুন।
ফ্যান্টাস্টিক

30

কোনও ফাংশন বেশি লোড করার জন্য, ডিফল্টরূপে নাল হিসাবে প্যারামিটারটি পাস করুন,

class ParentClass
{
   function mymethod($arg1 = null, $arg2 = null, $arg3 = null)  
     {  
        if( $arg1 == null && $arg2 == null && $arg3 == null ){ 
           return 'function has got zero parameters <br />';
        }
        else
        {
           $str = '';
           if( $arg1 != null ) 
              $str .= "arg1 = ".$arg1." <br />";

           if( $arg2 != null ) 
              $str .= "arg2 = ".$arg2." <br />";

           if( $arg3 != null ) 
              $str .= "arg3 = ".$arg3." <br />";

           return $str;
         }
     }
}

// and call it in order given below ...

 $obj = new ParentClass;

 echo '<br />$obj->mymethod()<br />';
 echo $obj->mymethod();

 echo '<br />$obj->mymethod(null,"test") <br />';
 echo $obj->mymethod(null,'test');

 echo '<br /> $obj->mymethod("test","test","test")<br />';
 echo $obj->mymethod('test','test','test');

4
আমি ডিফল্ট প্যারামিটারটিকে ফাংশন ওভারলোডিং হিসাবে বিবেচনা করি না। ফাংশন [বা পদ্ধতি] ওভারলোডিংয়ের সাথে পাস করা আর্গুমেন্টের ধরণের ভিত্তিতে আলাদা বাস্তবায়ন কল করার সাথে আরও অনেক কিছু রয়েছে। ডিফল্ট পরামিতি ব্যবহার করা আপনাকে কম প্যারামিটারের সুবিধার্থে একই বাস্তবায়নটি কল করতে দেয় allows
স্কেলেবল

1
হ্যাঁ, আপনি এটিকে টাইপ ভিত্তিতেও চালিত করতে পারেন তবে আপনি যদি পিএইচপি শিথিলভাবে টাইপ করা ভাষা জানেন এবং এটির মোকাবেলা করার জন্য এটি মোকাবেলা করা প্রয়োজন।
আদিল আব্বাসি

1
আমি গৃহীত উত্তরটির এই উত্তরটিকে অগ্রাধিকার দিচ্ছি, কারণ এটি ন্যূনতম এবং সর্বাধিক সংখ্যক পরামিতিগুলির হওয়া উচিত licit (প্রয়োজনীয় প্যারামিটারগুলির জন্য একটি ডিফল্ট মান সরবরাহ করবেন না)) @ স্কেল্যাবল - আমি আদিলের সাথে একমত যে, পিএইচপি যেহেতু স্বল্পভাবে টাইপ করা হয়, কার্যকরভাবে এটি পিএইচপি overloadকোনও ফাংশনে বোঝাতে পারে - তা সত্ত্বেও, আপনি একটি কার্যকর পয়েন্ট তৈরি করেন পাঠকদের সচেতন হওয়া উচিত।
টুলমেকারস্টেভ

11

এটি কারও কাছে হ্যাকিশ হতে পারে তবে কেকফ্প কীভাবে কিছু ফাংশন করে এবং এটিকে মানিয়ে নিয়েছে তা থেকে আমি এইভাবে শিখেছি কারণ এটি তৈরি করার নমনীয়তাটি আমার পছন্দ হয় I

ধারণাটি হ'ল আপনার কাছে বিভিন্ন ধরণের আর্গুমেন্ট, অ্যারে, অবজেক্টস ইত্যাদি রয়েছে, তবে আপনি কী পাস করেছেন তা সনাক্ত করে সেখান থেকে যান

function($arg1, $lastname) {
    if(is_array($arg1)){
        $lastname = $arg1['lastname'];
        $firstname = $arg1['firstname'];
    } else {
        $firstname = $arg1;
    }
    ...
}

1
নাহ আমি এটিকে হ্যাকিশ হিসাবে দেখছি না, পিএইচপি তার অনেকগুলি বিল্ট-ইন ফাংশনগুলির জন্য এটি করে।
BoltClock

যেহেতু পিএইচপি আলগাভাবে টাইপ করা হয়, ঠিক এইভাবে একজনকে এই পরিস্থিতিটি পরিচালনা করতে হবে । পিএইচপি-তে এর "প্রয়োজনীয় হ্যাকিশনেস"।
টুলমেকারস্টেভ

11
<?php   
/*******************************
 * author  : hishamdalal@gmail.com 
 * version : 3.8
 * create on : 2017-09-17
 * updated on : 2020-01-12
 *****************************/

#> 1. Include Overloadable class

class Overloadable
{
    static function call($obj, $method, $params=null) {
        $class = get_class($obj);
        // Get real method name
        $suffix_method_name = $method.self::getMethodSuffix($method, $params);

        if (method_exists($obj, $suffix_method_name)) {
            // Call method
            return call_user_func_array(array($obj, $suffix_method_name), $params);
        }else{
            throw new Exception('Tried to call unknown method '.$class.'::'.$suffix_method_name);
        }
    }

    static function getMethodSuffix($method, $params_ary=array()) {
        $c = '__';
        if(is_array($params_ary)){
            foreach($params_ary as $i=>$param){
                // Adding special characters to the end of method name 
                switch(gettype($param)){
                    case 'array':       $c .= 'a'; break;
                    case 'boolean':     $c .= 'b'; break;
                    case 'double':      $c .= 'd'; break;
                    case 'integer':     $c .= 'i'; break;
                    case 'NULL':        $c .= 'n'; break;
                    case 'object':
                        // Support closure parameter
                        if($param instanceof Closure ){
                            $c .= 'c';
                        }else{
                            $c .= 'o'; 
                        }
                    break;
                    case 'resource':    $c .= 'r'; break;
                    case 'string':      $c .= 's'; break;
                    case 'unknown type':$c .= 'u'; break;
                }
            }
        }
        return $c;
    }
    // Get a reference variable by name
    static function &refAccess($var_name) {
        $r =& $GLOBALS["$var_name"]; 
        return $r;
    }
}
//----------------------------------------------------------
#> 2. create new class
//----------------------------------------------------------

class test 
{
    private $name = 'test-1';

    #> 3. Add __call 'magic method' to your class

    // Call Overloadable class 
    // you must copy this method in your class to activate overloading
    function __call($method, $args) {
        return Overloadable::call($this, $method, $args);
    }

    #> 4. Add your methods with __ and arg type as one letter ie:(__i, __s, __is) and so on.
    #> methodname__i = methodname($integer)
    #> methodname__s = methodname($string)
    #> methodname__is = methodname($integer, $string)

    // func(void)
    function func__() {
        pre('func(void)', __function__);
    }
    // func(integer)
    function func__i($int) {
        pre('func(integer '.$int.')', __function__);
    }
    // func(string)
    function func__s($string) {
        pre('func(string '.$string.')', __function__);
    }    
    // func(string, object)
    function func__so($string, $object) {
        pre('func(string '.$string.', '.print_r($object, 1).')', __function__);
        //pre($object, 'Object: ');
    }
    // func(closure)
    function func__c(Closure $callback) {

        pre("func(".
            print_r(
                array( $callback, $callback($this->name) ), 
                1
            ).");", __function__.'(Closure)'
        );

    }   
    // anotherFunction(array)
    function anotherFunction__a($array) {
        pre('anotherFunction('.print_r($array, 1).')', __function__);
        $array[0]++;        // change the reference value
        $array['val']++;    // change the reference value
    }
    // anotherFunction(string)
    function anotherFunction__s($key) {
        pre('anotherFunction(string '.$key.')', __function__);
        // Get a reference
        $a2 =& Overloadable::refAccess($key); // $a2 =& $GLOBALS['val'];
        $a2 *= 3;   // change the reference value
    }

}

//----------------------------------------------------------
// Some data to work with:
$val  = 10;
class obj {
    private $x=10;
}

//----------------------------------------------------------
#> 5. create your object

// Start
$t = new test;

#> 6. Call your method

// Call first method with no args:
$t->func(); 
// Output: func(void)

$t->func($val);
// Output: func(integer 10)

$t->func("hello");
// Output: func(string hello)

$t->func("str", new obj());
/* Output: 
func(string str, obj Object
(
    [x:obj:private] => 10
)
)
*/

// call method with closure function
$t->func(function($n){
    return strtoupper($n);
});

/* Output:
func(Array
(
    [0] => Closure Object
        (
            [parameter] => Array
                (
                    [$n] => 
                )

        )

    [1] => TEST-1
)
);
*/

## Passing by Reference:

echo '<br><br>$val='.$val;
// Output: $val=10

$t->anotherFunction(array(&$val, 'val'=>&$val));
/* Output:
anotherFunction(Array
(
    [0] => 10
    [val] => 10
)
)
*/

echo 'Result: $val='.$val;
// Output: $val=12

$t->anotherFunction('val');
// Output: anotherFunction(string val)

echo 'Result: $val='.$val;
// Output: $val=36







// Helper function
//----------------------------------------------------------
function pre($mixed, $title=null){
    $output = "<fieldset>";
    $output .= $title ? "<legend><h2>$title</h2></legend>" : "";
    $output .= '<pre>'. print_r($mixed, 1). '</pre>';
    $output .= "</fieldset>";
    echo $output;
}
//----------------------------------------------------------

4
এই ক্লাসটি কীভাবে ব্যবহার করবেন আপনি কিছু ব্যাখ্যা যোগ করতে পারেন?
জাস্টাস রোমিজন

1- নতুন ক্লাস 2 তৈরি করুন - ওভারলোডযোগ্য প্রসারিত। 3- ফানকনাম_ () => কোনও আরগ বা ফানকাম_ ($ গুলি) => স্ট্রিং আরগের মতো ফাংশন তৈরি করুন
হিশাম দালাল

1
এটি বেশ দুর্দান্ত সমাধান। আপনি কেন $ o = নতুন $ আপত্তি () করেন? আমি এখনও এটি চেষ্টা করে দেখিনি, যদিও আমি মনে করি এটি \ $ o = \ $ হওয়া উচিত?
over_optimistic

এই গুরুত্বপূর্ণ বিজ্ঞপ্তির জন্য আপনাকে ধন্যবাদ, এবং আমি ব্যাকস্ল্যাশ ব্যবহার করব, তবে এটি ব্যাকস্ল্যাশ এবং ছাড়াই কাজ করছে! - আমি স্থানীয় সার্ভার হিসাবে phpEazy ব্যবহার করি।
হিশাম দালাল


3

পিএইচপি 5.6 আপনি ব্যবহার করতে পারেন splat অপারেটর ... গত প্যারামিটার হিসাবে এবং সঙ্গে দূরে না func_get_args()এবং func_num_args():

function example(...$args)
{
   count($args); // Equivalent to func_num_args()
}

example(1, 2);
example(1, 2, 3, 4, 5, 6, 7);

আপনি এটি যুক্তিগুলি আনপ্যাক করতেও ব্যবহার করতে পারেন:

$args[] = 1;
$args[] = 2;
$args[] = 3;
example(...$args);

এর সমতুল্য:

example(1, 2, 3);

1
<?php

    class abs
    {
        public function volume($arg1=null, $arg2=null, $arg3=null)
        {   
            if($arg1 == null && $arg2 == null && $arg3 == null)
        {
            echo "function has no arguments. <br>";
        }

        else if($arg1 != null && $arg2 != null && $arg3 != null)
            {
            $volume=$arg1*$arg2*$arg3;
            echo "volume of a cuboid ".$volume ."<br>";
            }
            else if($arg1 != null && $arg2 != null)
            {
            $area=$arg1*$arg2;
            echo "area of square  = " .$area ."<br>";
            }
            else if($arg1 != null)
            {
            $volume=$arg1*$arg1*$arg1; 
            echo "volume of a cube = ".$volume ."<br>";
            }


        }


    }

    $obj=new abs();
    echo "For no arguments. <br>";
    $obj->volume();
    echo "For one arguments. <br>";
    $obj->volume(3);
    echo "For two arguments. <br>";
    $obj->volume(3,4);
    echo "For three arguments. <br>";
    $obj->volume(3,4,5);
    ?>

প্রশ্নটি সম্পাদনা করার চেষ্টা করুন এবং বিন্যাস ব্যবহার করুন। এটি আপনার উত্তরকে আরও পঠনযোগ্য করে তুলবে এবং আরও বেশি ব্যবহারকারীদের আকর্ষণ করবে।
কাশীশ অরোরা


0

পিএইচপি আপাতত ওভারলোডিং সমর্থন করে না। আশা করি এটি অন্যান্য প্রোগ্রামিং ভাষার মতো অন্যান্য সংস্করণেও প্রয়োগ করা হবে।

এই লাইব্রেরিটি চেকআউট করুন, এটি আপনাকে ক্লোজারগুলির ক্ষেত্রে পিএইচপি ওভারলোডিং ব্যবহার করার অনুমতি দেবে। https://github.com/Sahil-Gulati/Overloading


1
আপনি যদি এই জাতীয় বিবৃতি দিতে যাচ্ছেন তবে আপনি যে সংস্করণগুলি উল্লেখ করছেন সেগুলিকে সত্যই অন্তর্ভুক্ত করা উচিত, যেভাবে লোকেরা জানবে যে কোনও মন্তব্য ভবিষ্যতের তারিখে যখন তারা দেখবে তখন তার তারিখ
কতটা পুরানো

0

দুঃখজনকভাবে পিএইচপি তে কোনও ওভারলোড নেই কারণ এটি সি # তে করা হয়েছে। তবে আমার একটু কৌশল আছে। আমি ডিফল্ট নাল মানগুলির সাথে যুক্তিগুলি ঘোষণা করি এবং একটি ফাংশনে তাদের পরীক্ষা করি। এইভাবে আমার ফাংশনটি আর্গুমেন্টের উপর নির্ভর করে বিভিন্ন জিনিস করতে পারে। নীচে সহজ উদাহরণ:

public function query($queryString, $class = null) //second arg. is optional
{
    $query = $this->dbLink->prepare($queryString);
    $query->execute();

    //if there is second argument method does different thing
    if (!is_null($class)) { 
        $query->setFetchMode(PDO::FETCH_CLASS, $class);
    }

    return $query->fetchAll();
}

//This loads rows in to array of class
$Result = $this->query($queryString, "SomeClass");
//This loads rows as standard arrays
$Result = $this->query($queryString);

1
নতুন এক বছর পরে নতুন লেখার আগে দয়া করে সমস্ত বিদ্যমান উত্তরগুলি পড়ুন। এই কৌশলটি উপরের উত্তরে ইতিমধ্যে দু'বার প্রদর্শিত হয়েছিল। একবার 2013 সালে, এবং আবার 2014.
ToolmakerSteve
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.