一般的函数就不介绍了,这里主要介绍几种难以理解的函数。
2.3.1、引用参数的函数
引用参数函数,就是在函数的参数前加了一个&符号。
一般的函数,在调用后,即便函数内修改了参数的值,但是也不会修改函数外部的值。因为函数的参数也属于局部变量。
如果希望在调用函数后,函数的参数值在内部变化了,该参数在函数外部也跟着变化,那么需要使用引用参数。
eg:
function test(&$a){
$a = 2;
}
$b = 1;
test($b);
echo $b;//输出2,在调用test()函数时,$b的值被修改。
需要注意的是:
1、引用传参,不能传具体的值,只能传变量。
2、传参时,不能含&符号,例如上例中调用函数test($b)。
在PHP内置函数中,有很多函数都用到了引用传参。
eg:
$a = array(10,2,6,1,8,23);
sort($a);//sort函数使用了引用传参,和上面那个例子类似
var_dump($a);//输出array(1,2,6,8,10,23);
2.3.2、可变参数数量函数
PHP 在用户自定义函数中支持可变数量的参数列表。在 PHP 5.6 及以上的版本中,由 … 语法实现;在 PHP 5.5 及更早版本中,使用函数 func_num_args(),func_get_arg(),和 func_get_args() 。这些函数在php7中一直还是支持的。
使用…语法示例:
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
func_num_args()返回参数的个数
eg:
function foo()
{
$numargs = func_num_args();
echo "$numargs";
}
foo(1, 2, 3); //输出3
func_get_arg() ,说明:
mixed func_get_arg ( int $arg_num )
从用户自定义函数的参数列表中获取某个指定的参数。$arg_num
从0开始计数,返回指定的参数,错误则返回 FALSE 。
eg:
function foo()
{
$numargs = func_num_args();
echo "Number of arguments: $numargs
\n";
if ($numargs >= 2) {
echo "Second argument is: " . func_get_arg(1) . "
\n";
}
}
foo (1, 2, 3);
func_get_args() ——返回一个数组,其中每个元素都是目前用户自定义函数的参数列表的相应元素的副本。
eg:
function foo()
{
$numargs = func_num_args();
echo "Number of arguments: $numargs
\n";
if ($numargs >= 2) {
echo "Second argument is: " . func_get_arg(1) . "
\n";
}
$arg_list = func_get_args();
for ($i = 0; $i < $numargs; $i++) {
echo "Argument $i is: " . $arg_list[$i] . "
\n";
}
var_export($arg_list);
}
foo(1, 2, 3);
在php系统函数中,存在很多这种可变参数的函数,例如array_merge(),array()等。
2.3.3、回调函数
1、变量函数
不多解释,看示例:
function test($a,$b){
return $a+$b;
}
$res = "test";
echo $res(1,2);
//变量函数回调函数
function test($a){
for($i=0;$i<100;$i++){
if($a($i)){
continue;
}
echo $i."
";
}
}
function b($c){
return $c%3 == 0;
}
test("b");//这里参是b函数,调用需要双引号
2、利用call_user_func_array函数自定义回调函数
说明:
mixed call_user_func_array ( callable $callback , array $param_arr )
返回回调函数的结果。如果出错的话就返回FALSE。
参数:
callback
被调用的回调函数。
param_arr
要被传入回调函数的数组,这个数组得是索引数组。
$func = function($arg1, $arg2 = 4) {
return $arg1 * $arg2;
};
var_dump(call_user_func_array($func, array(2,5)));//输出10
//传引用
function mega(&$a){
$a = 55;
echo "function mega \$a=$a\n";
}
$bar = 77;
call_user_func_array('mega',array(&$bar));//输出55
echo "global \$bar=$bar\n";//输出55
//可变参数
function foo ($a, $b) {
return $a + $b;
}
$func = 'foo';
$values = array(1, 2);
call_user_func_array($func, $values);
$func(...$values);
3、类静态函数和对象方法回调
class a{
static function test1($a,$b){
echo $a;
echo $b;
}
}
class b{
function test2($a,$b){
echo $a;
echo $b;
}
}
call_user_func_array(array('a','test1'),array(1,2));//静态方法调用
call_user_func_array(array(new b(),'test2'),array(1,2));//非静态方法调用
回调方法调用总结(callfunc表示所有回调函数):
1)callfunc(“函数名字字符串”);//回调全局函数
2)callfunc(array(‘类名称’ , ‘类中静态方法名称’) , array(‘静态方法中的参数’));//回调类中静态方法
3)callfunc(array(对象 , ‘类中方法名称’) , array(‘方法中的参数’));//回调对象中成员的方法,也可以用此方式调用静态成员方法
2.3.4、递归函数
递归函数就是只调用函数,在函数内部直接或间接的调自己。递归函数的好处是会精简重复调用程序,例如列表、动态树型菜单、遍历目录等操作。虽然非递归函数效率更高,但是比较难编程,并且可读性差。
eg:
function test($n){
echo $n."  ";
if($n>0){
test($n-1);
}else{
echo "<-->";
}
echo $n."  ";
}
test(10);//输出10 9 8 7 6 5 4 3 2 1 0 <-->0 1 2 3 4 5 6 7 8 9 10
上面的示例相对来说比较不好理解,下面另举一个示例解释这个输出结果。
下面示例中,和上面的示例中类似,a、b、c函数可以看成同一个名称的函数,重复的调用自己。
function a($n){
echo $n;
b($n-1);
echo $n;
}
function b($n){
echo $n;
c($n-1);
echo $n;
}
function c($n){
echo $n;
}
a(3);//输出32123
2.3.5匿名函数(闭包函数)
匿名函数,也叫闭包函数(closures),其实匿名函数更贴切。允许临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值。当然,也有其它应用的情况。
下面举例来说明匿名函数:
eg1:匿名函数变量赋值示例
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('PHP');
eg2:
闭包可以从父作用域中继承变量。 任何此类变量都应该用 use 语言结构传递进去。该示例主要说明传参使用use和&符号作用。这些变量都必须在函数或类的头部声明。
$message = 'hello';
// 没有 "use"
$example = function () {
var_dump($message);
};
echo $example();//由于没有用use,没有继承变量,导致报变量未定义错误,并输出null
// 使用use,继承 $message
$example = function () use ($message) {
var_dump($message);
};
echo $example();//继承了变量$message,并输出hello
//此例为说明引用的是$message的副本
$message = 'world';
echo $example();//此时输出的依然是'hello'
// &符号的使用,对变量$message的完全引用
$message = 'My';
$example = function () use (&$message) {
var_dump($message);
};
echo $example();//输出'My'
$message = 'love';
echo $example();//输出'love'
//另一种传参方法
$example = function ($arg) use ($message) {
var_dump($message. ' ' .$arg);
};
$example("you");//输出'love you'
eg3:
php官网提供了实例,如下
// 一个基本的购物车,包括一些已经添加的商品和每种商品的数量。
// 其中有一个方法用来计算购物车中所有商品的总价格,该方法使
// 用了一个 closure 作为回调函数。
class Cart
{
const PRICE_BUTTER = 1.00;
const PRICE_MILK = 3.00;
const PRICE_EGGS = 6.95;
protected $products = array();
public function add($product, $quantity)
{
$this->products[$product] = $quantity;
}
public function getQuantity($product)
{
return isset($this->products[$product]) ? $this->products[$product] : FALSE;
}
public function getTotal($tax)
{
$total = 0.00;
$callback =
function ($quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};
array_walk($this->products, $callback);//$callback函数中的$quantity和$product此时是$this->products中的键值和键名
return round($total, 2);
}
}
$my_cart = new Cart;
// 往购物车里添加条目
$my_cart->add('butter', 1);
$my_cart->add('milk', 3);
$my_cart->add('eggs', 6);
// 打出出总价格,其中有 5% 的销售税.
print $my_cart->getTotal(0.05) . "\n";
// 最后结果是 54.29