PHP函数重载

来自C ++的背景;)
我如何重载PHP函数?

一个函数定义,如果有任何参数,另一个如果没有参数? 在PHP中可能吗? 或者我应该使用否则检查是否有任何parameter passing$ _GET和POST? 并把它们联系起来

你不能重载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); 

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) { } } 

要过载一个函数,只需要将参数默认传递为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'); 

对某些人来说,这可能是个骇人听闻的问题,但是我从Cakephp如何执行某些function并对其进行了调整,从而学到了这一点,因为我喜欢它创build的灵活性

这个想法是你有不同types的参数,数组,对象等,然后你检测你通过了什么,并从那里

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

真正的过载(版本3.8)“没有延长”+“支持closures”

 /******************************* * 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 

真正的过载“不扩展”(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 

真正的过载(版本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(); 

真正的过载(版本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() ); 

那这个呢:

 function($arg = NULL) { if ($arg != NULL) { etc. etc. } } 
 <?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); ?> 

目前PHP不支持重载。 希望这会在其他版本像其他编程语言一样实现。

检出这个库,这将允许你在closures方面使用PHP重载。 https://github.com/Sahil-Gulati/Overloading