복붙노트

PHP 함수 오버로딩

PHP

PHP 함수 오버로딩

C ++ 배경부터;) 어떻게 PHP 함수를 오버로드 할 수 있습니까?

인자가 있다면 함수 정의 하나, 인자가 없다면 또 다른 함수 정의? PHP로 가능합니까? 또는 다른 경우 $ _GET 및 POST 전달 된 매개 변수가 있는지 확인하려면 사용해야합니까 ?? 그들을 연관 시키시겠습니까?

해결법

  1. ==============================

    1.PHP 함수를 오버로드 할 수 없습니다. 함수 시그니처는 이름에만 기반을두고 인수 목록을 포함하지 않으므로 동일한 이름을 가진 두 개의 함수를 가질 수 없습니다. 클래스 메소드 오버로딩은 다른 많은 언어와 PHP에서 다릅니다. PHP는 같은 단어를 사용하지만 다른 패턴을 설명합니다.

    PHP 함수를 오버로드 할 수 없습니다. 함수 시그니처는 이름에만 기반을두고 인수 목록을 포함하지 않으므로 동일한 이름을 가진 두 개의 함수를 가질 수 없습니다. 클래스 메소드 오버로딩은 다른 많은 언어와 PHP에서 다릅니다. PHP는 같은 단어를 사용하지만 다른 패턴을 설명합니다.

    그러나 변수 수를 취하는 가변 함수를 선언 할 수 있습니다. 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);
    
  2. ==============================

    2.PHP는 전통적인 메서드 오버로딩을 지원하지 않지만 원하는 것을 얻을 수있는 방법 중 하나는 __call 매직 메서드를 사용하는 것입니다.

    PHP는 전통적인 메서드 오버로딩을 지원하지 않지만 원하는 것을 얻을 수있는 방법 중 하나는 __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) {
    
        }
    
    }
    
  3. ==============================

    3.함수를 과도하게로드하려면 기본적으로 매개 변수를 null로 전달하십시오.

    함수를 과도하게로드하려면 기본적으로 매개 변수를 null로 전달하십시오.

    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. ==============================

    4.어떤 사람들에게는 hackish가 될 수도 있지만 Cakephp가 어떤 기능을 수행 하는지를이 방법을 통해 알게되었고, 내가 만든 유연성을 좋아하기 때문에 그것을 적용했습니다.

    어떤 사람들에게는 hackish가 될 수도 있지만 Cakephp가 어떤 기능을 수행 하는지를이 방법을 통해 알게되었고, 내가 만든 유연성을 좋아하기 때문에 그것을 적용했습니다.

    아이디어는 당신이 인수, 배열, 객체 등등의 다른 유형을 가지고있다, 그러면 당신은 당신이 통과되고 거기에서부터 이동 한 것을 탐지합니다.

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

    5.Real Overload (버전 3.8) "확장없는"+ "클로저 지원"

    Real Overload (버전 3.8) "확장없는"+ "클로저 지원"

    /*******************************
     * author  : hishamdalal@gmail.com 
     * version : 3.8
     * create on : 2017-09-17
     *****************************/
    
    
    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;
        }
    }
    
    class test 
    {
        private $name = 'test-1';
    
        // Call Overloadable class 
        // you must copy this method in your class to activate overloading
        function __call($method, $args) {
            return Overloadable::call($this, $method, $args);
        }
    
        // func(closure)
        function func__c(Closure $callback) {
            pre("func__c(".print_r($callback, 1).");", 'print_r(Closure)');
            return $callback($this->name);
        }   
    }
    
    //----------------------------------------------------------
    // Start
    $t = new test;
    
    pre($t->func(function($n){ return strtoupper($n);}), 'Closure');
    
    //----------------------------------------------------------
    function pre($mixed, $title=null, $print=true){
        $output = "";
        if(empty($mixed)){
            $output .= "<div><h3>-->Empty $title<--</h3></div>";
            if($print) echo $output;
            else return $output;
        }
        $output .= "<fieldset>";
        if($title){$output .= "<legend><h2>$title</h2></legend>";}
        $output .= '<pre>';
        $output .= print_r($mixed, 1);
        $output .= '</pre>';
        $output .= "</fieldset>";
        if($print) echo $output;
        else return $output;
    }
    //----------------------------------------------------------
    

    산출:

    ---- print_r(Closure) ----
    
    func__c(Closure Object
    (
        [parameter] => Array
            (
                [$n] => 
            )
    
    )
    );
    
    ---- Closure ----
    
    TEST-1
    

    Real Overload "확장하지 않음"(버전 3.7)

    <?php
    
    /*******************************
     * author  : hishamdalal@gmail.com 
     * version : 3.7
     * date    : 2014-12-01
     *****************************/
    
    class Overloadable
    {
        static function call($obj, $method, $params=null) {
            // 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);
                #return $obj->$suffix_method_name($params);
            } else {
                $class = get_class($obj);
                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':      $c .= 'o'; break;
                        case 'resource':    $c .= 'r'; break;
                        case 'string':      $c .= 's'; break;
                    }
                }
            }
            return $c;
        }
        // Get a reference variable by name
        static function &refAccess($var_name) {
            $r =& $GLOBALS["$var_name"]; 
            return $r;
        }
    
    }
    
    
    class test 
    {
        // Call Overloadable class 
        // you must copy this method in your class to activate overloading
        function __call($method, $args) {
            return Overloadable::call($this, $method, $args);
        }
        // myFunction(void)
        function myFunction__() {
            echo 'myFunction(void)';
        }
        // myFunction(integer)
        function myFunction__i($int) {
            echo 'myFunction(integer='.$int.')';
        }
        // myFunction(string)
        function myFunction__s($string) {
            echo 'myFunction(string='.$string.')';
        }    
        // myFunction(string)
        function myFunction__so($string, $object) {
            echo 'myFunction(string='.$string.', object='.get_class($object).')';
            echo '<pre>Object: ';
            print_r($object);
            echo '</pre>';
        }
        // anotherFunction(array)
        function anotherFunction__a($array) {
            echo 'anotherFunction('.print_r($array, 1).')';
            $array[0]++;        // change the reference value
            $array['val']++;    // change the reference value
        }
        // anotherFunction(string, integer)
        function anotherFunction__si($key, $value) {
            echo 'anotherFunction(string='.$key.', integer='.$value.')';
            // 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;
    }
    //----------------------------------------------------------
    
    // Start
    $t = new test;
    
    // Call first method with no args:
    $t->myFunction(); 
    // Output: myFunction(void)
    echo '<hr>';
    
    $t->myFunction($val);
    // Output: myFunction(integer=10)
    echo '<br>';
    
    $t->myFunction("hello");
    // Output: myFunction(string=hello)
    echo '<br>';
    
    $t->myFunction("str", new obj());
    /* Output: 
    myFunction(string=str, object=obj)
    Object: obj Object
    (
        [x:obj:private] => 10
    )
    */
    
    ## Passing by Reference:
    
    echo '<hr>';
    echo '$val='.$val;
    // Output: $val=10
    echo '<br>';
    $t->anotherFunction(array(&$val, 'val'=>&$val));
    // Output: anotherFunction(Array ( [0] => 10 [val] => 10 ) )
    echo '<br>';
    echo '$val='.$val;
    // Output: $val=12
    
    echo '<hr>';
    $t->anotherFunction('val', $val);
    // Output: anotherFunction(string=val, integer=12)
    echo '<br>';
    echo '$val='.$val;
    // Output: $val=36
    

    Real Overload (버전 3.5) :

    /*******************************
     * author  : hishamdalal@gmail.com 
     * version : 3.5
     * date    : 2014-11-16
     *****************************/
    
    class Overloadable 
    {
        // Magic Method
        public function __call($method, $params) {
            $class = get_class($this);
            // Get real method name
            $suffix_method_name = $method.$this->getMethodSuffix($method, $params);
    
            if (method_exists($this, $suffix_method_name)){
                // Call method
                return call_user_func_array(array($this, $suffix_method_name), $params);
            }else{
                throw new Exception('Tried to call unknown method '.$class.'::'.$suffix_method_name);
            }
        }
    
        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 'integer':     $c .= 'i'; break;
                        case 'double':      $c .= 'd'; break;
                        case 'string':      $c .= 's'; break;
                        case 'array':       $c .= 'a'; break;
                        case 'object':      $c .= 'o'; break;
                        case 'resource':    $c .= 'r'; break;
                        case 'NULL':        $c .= 'n'; break;
                    }
                }
            }
            return $c;
        }
        // Get reference variable by name
        function &refAccess($var_name){
            $r =& $GLOBALS["$var_name"]; 
            return $r;
        }
    }
    
    //------------------------------------------------------------------------//
    ## Inherit "Overloadable" class to enable overloading
    class test extends Overloadable
    {
            // myFunction(void)
            function myFunction__() {           
                echo  "Hi<br>";
            }
    
            // myFunction(integer, string)
            function myFunction__is($a, $s) {
                echo  "$a, $s<br>";
            }
    
            // myFunction(array)
            function myFunction__a($a) {
                $a[0]++; // change the reference value
                $a[1]++;  // change value locally (method scope) 
            }
    
            // myFunction(integer)
            function myFunction__i($b) {
                // $GLOBALS['val2']
                $b2 =& $this->refAccess('val2');
                $b2 *= 3;   // change the reference value
            }
    
            // myFunction(string, string)
            function myFunction__ss($a, $b) {
                // $this->refAccess('obj')->plus()
                $this->refAccess($a)->plus();
    
                #$b1 =& $GLOBALS["$b"]; 
                $b1 =& $this->refAccess($b); 
                $b1++;
                $b1++;
            }
    
            // myFunction(object, integer, array)
            function myFunction__oia($a, $b, $ary) {
                // Get arguments names
                $obj_name = $ary[0];
                $val_name = $ary[1];
    
                // Get argument reference
                $a1 =& $this->refAccess($obj_name); 
                $a1->plus();
    
                $b1 =& $this->refAccess($val_name);
                $b1+= $b;
            }
    
            // Just a normal method
            function welcome(){
                echo "Welcome!";
            }
    
    }
    //------------------------------------------------------------------------//
    // Some data types to work with:
    class  obj {
        private $v=0;
        function plus(){
            $this->v++;
        }
        function result(){
            return $this->v;
        }
    }
    $val  = 10;
    $val2 = 10;
    $obj = new obj();
    
    // Show Default values
    echo "\$val = $val, \$val2 = $val2, ";
    echo 'obj->v =' . $obj->result()."<hr>";
    //------------------------------------------------------------------------//
    
    // Start
    $t = new test();
    
    
    // Call first method with no args:
    echo 'myFunction__():<br>';
    $t->myFunction();
    echo "<hr>";
    
    
    echo 'myFunction__is(integer, string):<br>';
    $t->myFunction($val, 'text');
    echo "\$val = $val, \$val2 = $val2<hr>";
    
    
    echo 'myFunction__i(integer):<br>';
    $t->myFunction($val);
    echo "\$val = $val, \$val2 = $val2<hr>";
    
    ## Passing by Reference:
    
    // 1) The best way to pass arguments
    echo 'myFunction__a(array):<br>';
    //Passing first item by reference
    $t->myFunction(array(&$val, $val2));
    echo "\$val = $val, \$val2 = $val2<hr>";
    
    // 2) Passing arguments names
    echo 'myFunction__ss(string, string):<br>';
    // Pass object name and variable name
    $t->myFunction('obj', 'val');
    echo "\$val = $val, \$val2 = $val2, ";
    echo 'obj->v =' . $obj->result()."<hr>";
    
    // 3) Passing arguments values and names
    echo 'myFunction__oia(object, integer, array):<br>';
    // Pass object, integer values and passing there names as array
    $t->myFunction($obj, $val, array('obj', 'val'));
    echo "\$val = $val, \$val2 = $val2, ";
    echo 'obj->v =' . $obj->result()."<hr>";
    
    // Just a normal method
    echo 'welcome():<br>';
    $t->welcome();
    

    Real Overload (버전 3.1) :

    /*******************************
     * author  : hishamdalal@gmail.com 
     * version : 3.1
     * date    : 2013-04-11
     *****************************/
    
    class overloadable
    {
        protected $fname = null;
        protected $fargs = array();
    
        //--------------------------------------------------//
        function set($obj, $fname, $args){
            $n = ''; 
            $type = $this->getType($args); 
            $n  = "\$o = new $obj();\n";
            $n .= "if(method_exists(\$o, '$fname"."_$type')){\n";
            $n .= "\t\$r = \$o->$fname"."_$type(". $this->getArgsName($args) .");\n";
            $n .= "}else{\n\t\$r = null;\n";
            $n .= "\ttrigger_error('function ".$fname."_".$type." is not exist!');\n}";
            eval("\$r = $n;");
            return $r;
        }
        //--------------------------------------------------//
        function getType($args) {
            $argType = array();
            foreach($args as $i=>$val) {
                $argType[$i][] = $this->getSuffix($val, $i) ;
            }
            $s = '';
            if(is_array($argType)){
                foreach($argType as $type){
                    $s  .= implode('', $type);
                }
                return $s;
            }
            return implode('', $argType);
        }   
        //--------------------------------------------------//
        function getSuffix($byValarg, $i) {
                if( is_numeric($byValarg) ) {
                    $type = 'N'; 
                    $this->fargs['N'.$i] = $byValarg;
                } elseif( is_array($byValarg) ) {
                    $type = 'A';
                    $this->fargs['A'.$i] = $byValarg;
                } elseif( is_object($byValarg) ) {
                    $type = 'O'; 
                    $this->fargs['O'.$i] = $byValarg;
                } elseif( is_resource($byValarg) ) {
                    $type = 'R'; 
                    $this->fargs['R'.$i] = $byValarg;
                } else {
                    $type = 'S'; 
                    $this->fargs['S'.$i] = $byValarg;
                }   
                return $type;
        }
        //--------------------------------------------------//
        function getArgsName($args){
            $r = array();
            $ary = array_keys($this->fargs);
            foreach( $ary as $k=>$v){
                $r[]='$this->fargs["'.$v.'"]';
            }
            return implode(", ", $r);
        }
        //--------------------------------------------------//  
        function __call($name, $args){
            $this->fargs = array();
            return $this->set(get_class($this), $name, $args);
        }
        //--------------------------------------------------//  
    }
    
    
    class test2 extends overloadable {
        function foo_(){
            echo 'foo - no args';
        }
        function foo_S($s){
            echo "foo - one string $s";
        }
        function foo_SS($s1, $s2){
            echo "foo - tow strings $s1, $s2";
        }   
        function foo_SN($s, $n){
            echo "foo - string and number $s, $n";
        }
        function foo_A($ary){
            print_r($ary);
        }
        function foo_AA($ary1, $ary2){
            if(is_array($ary1) && is_array($ary2)){
                echo "foo - tow arrays";
            }else{echo 0;}
        }   
        function foo_O($obj){
            echo "foo - ";
            print_r($obj);
        }
        function hi(){
            echo "hi - welcome!";
        }
    }
    
    echo '<pre>';
    $t = new test2();
    
    echo '<br />foo_: ';
    print_r( $t->foo() );
    
    echo '<br />foo_s: ';
    print_r( $t->foo('a') );
    
    echo '<br />foo_ss: ';
    print_r( $t->foo('a', 'b') );
    
    echo '<br />foo_sn: ';
    print_r( $t->foo('a', 2) );
    
    echo '<br />foo_snn: ';
    print_r( $t->foo('s', 2, 9) );
    
    echo '<br />foo_a: ';
    print_r( $t->foo(array(4,5,6,7)) );
    
    echo '<br />foo_aa: ';
    print_r( $t->foo( array(5,6,7), array(8,9,10) ) );
    
    echo '<br />foo_o: ';
    print_r( $t->foo($t) );
    
    echo '<br />hi: ';
    print_r( $t->hi() );
    
  6. ==============================

    6.이건 어때?

    이건 어때?

    function($arg = NULL) {
    
        if ($arg != NULL) {
            etc.
            etc.
        }
    }
    
  7. ==============================

    7.PHP 5.6에서는 마지막 매개 변수로 splat 연산자를 사용할 수 있으며 func_get_args () 및 func_num_args ()를 사용하지 않아도됩니다.

    PHP 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);
    
  8. ==============================

    8.

    <?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);
        ?>
    
  9. ==============================

    9.PHP는 현재 과부하를 지원하지 않습니다. 희망이 다른 프로그래밍 언어와 같은 다른 버전에서 구현됩니다.

    PHP는 현재 과부하를 지원하지 않습니다. 희망이 다른 프로그래밍 언어와 같은 다른 버전에서 구현됩니다.

    이 라이브러리를 체크 아웃하면 클로저와 관련하여 PHP 오버로딩을 사용할 수 있습니다. https://github.com/Sahil-Gulati/Overloading

  10. ==============================

    10.안타깝게도 C #에서는 PHP에서 과부하가 없습니다. 하지만 조금 트릭이있어. 인수를 기본 null 값으로 선언하고 함수에서이를 확인합니다. 그런 식으로 내 기능은 인수에 따라 다른 일을 할 수 있습니다. 다음은 간단한 예입니다.

    안타깝게도 C #에서는 PHP에서 과부하가 없습니다. 하지만 조금 트릭이있어. 인수를 기본 null 값으로 선언하고 함수에서이를 확인합니다. 그런 식으로 내 기능은 인수에 따라 다른 일을 할 수 있습니다. 다음은 간단한 예입니다.

    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);
    
  11. from https://stackoverflow.com/questions/4697705/php-function-overloading by cc-by-sa and MIT license