web-dev-qa-db-fra.com

PHP surcharge de fonction

Venant du fond C++;)
Comment surcharger PHP fonctions?

Une définition de fonction s'il y a des arguments, et une autre s'il n'y a pas d'arguments? Est-ce possible en PHP? Ou devrais-je utiliser if else pour vérifier si des paramètres ont été passés de $ _GET et POST ?? et les raconter?

185
Vamsi Krishna B

Vous ne pouvez pas surcharger les fonctions PHP. Les signatures de fonction sont basées uniquement sur leurs noms et n'incluent pas les listes d'arguments. Vous ne pouvez donc pas avoir deux fonctions portant le même nom. La classe surcharge de méthode est différente dans PHP que dans de nombreux autres langages. PHP utilise le même mot mais décrit un modèle différent.

Vous pouvez cependant déclarer une fonction variadique qui prend un nombre variable d'arguments. Vous devez utiliser func_num_args() et func_get_arg() pour obtenir les arguments passés et les utiliser normalement.

Par exemple:

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);
208
BoltClock

PHP ne prend pas en charge la surcharge de méthodes traditionnelles. Cependant, une façon de parvenir à vos objectifs consiste à utiliser la méthode magique __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) {

    }

}
75
Stephen

Pour surcharger une fonction, passez simplement le paramètre null par défaut,

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');
29
Adil Abbasi

C'est peut-être un peu ridicule pour certains, mais j'ai appris comment Cakephp remplit certaines fonctions et je l'ai adapté parce que j'aime la flexibilité que cela crée.

L'idée est que vous avez différents types d'arguments, tableaux, objets, etc., puis vous détectez ce que vous avez été passé et vous partez de là.

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

surcharge réelle (version 3.8) "sans extension" + "fermetures de support"

<?php   
/*******************************
 * author  : [email protected] 
 * version : 3.8
 * create on : 2017-09-17
 * updated on : 2019-01-23
 *****************************/

#> 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(closure)
    function func__c(Closure $callback) {
        // your code...
        pre("func__c(".print_r($callback, 1).");", 'print_r(Closure)');
        return $callback($this->name);
    }   
    // 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.', object='.get_class($object).')', __function__);
        pre($object, 'Object: ');
    }
    // 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;

pre(
    $t->func(function($n){
        return strtoupper($n);
    })
, 
'Closure');

#> 6. Call your method by typing first part before __ and add method $args if exist

// 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, object=obj)
Object: obj Object
(
    [x:obj:private] => 10
)
*/

## Passing by Reference:

echo '$val='.$val;
// Output: $val=10

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

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

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

echo '$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;
}
//----------------------------------------------------------
9
Hisham Dalal

Et ça:

function($arg = NULL) {

    if ($arg != NULL) {
        etc.
        etc.
    }
}
4
Marlin Ouverson

Dans PHP 5.6, vous pouvez utiliser le opérateur splat... comme dernier paramètre et supprimer les func_get_args() et func_num_args():

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

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

Vous pouvez également l'utiliser pour décompresser des arguments:

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

Est équivalent à:

example(1, 2, 3);
3
mtpultz
<?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);
    ?>
1
Raman Deep Bajwa

PHP ne supporte pas la surcharge pour le moment. J'espère que cela sera implémenté dans les autres versions comme dans d'autres langages de programmation.

Commander cette bibliothèque, Cela vous permettra d’utiliser PHP Surcharge en termes de fermetures. https://github.com/Sahil-Gulati/Overloading

0
Sahil Gulati

Malheureusement, il n'y a pas de surcharge dans PHP comme c'est le cas en C #. Mais j'ai un petit truc. Je déclare des arguments avec des valeurs NULL par défaut et les vérifie dans une fonction. De cette façon, ma fonction peut faire différentes choses en fonction des arguments. Voici un exemple simple:

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);
0
Rovshan Mamedov